题目描述:

给定一个数组,判断数组内是否存在一个连续区间,使其和恰好等于给定整数k。

输入:

输入包含多组测试用例,每组测试用例由一个整数n(1<=n<=10000)开头,代表数组的大小。

接下去一行为n个整数,描述这个数组,整数绝对值不大于100。

最后一行为一个整数k(大小在int范围内)。

输出:

对于每组测试用例,若存在这个连续区间,输出其开始和结束的位置,s,e(s <= e)。

若存在多个符合条件的输出,则输出s较小的那个,若仍然存在多个,输出e较小的那个。

若不存在,直接输出"No"。

样例输入:
5
-1 2 3 -4 9
5
3
-1 2 -3
7
2
-1 1
0
样例输出:
2 3
No
1 2
来源:
2014年王道论坛计算机考研机试全真模拟考试
我的解答:
package jobdu.wangdao;

import java.util.Scanner;

/**
* 题目描述: 给定一个数组,判断数组内是否存在一个连续区间,使其和恰好等于给定整数k。
*
*/
public class Question1554 { private static void solve(int[] array, int k) {
boolean find = false;
for (int i = 0; i < array.length; i++) {
if (!find) {
int sum = 0;
for (int j = i; j < array.length; j++) {
sum += array[j];
if (sum == k) {
find = true;
System.out.println((i + 1) + " " + (j + 1));
break;
}
}
}
}
if (!find)
System.out.println("No");
} public static void main(String[] args) { @SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int[] array = new int[n];
for (int i = 0; i < n; i++) {
array[i] = scanner.nextInt();
}
int k = scanner.nextInt();
solve(array, k);
}
}
}

  这个解答用的是暴力o(n*n)破解,提交后九道提示超时。

  用动态规划的思想,记录从a[0]开始到a[i]的和存入sum[i],那么当sum[i]-sum[j]=k的时候从a[j+1]到a[i]的和就为k。

package jobdu.wangdao;

import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 题目描述: 给定一个数组,判断数组内是否存在一个连续区间,使其和恰好等于给定整数k。
*
*/
public class Question1554 { /**
* 暴力求和比较
*
* @param array
* @param k
* @return
*/
public static Section solve(int[] array, int k) {
boolean find = false;
for (int i = 0; i < array.length; i++) {
if (!find) {
int sum = 0;
for (int j = i; j < array.length; j++) {
sum += array[j];
if (sum == k) {
find = true;
System.out.println((i + 1) + " " + (j + 1));
return new Section(i + 1, j + 1);
}
}
}
}
if (!find)
System.out.println("No");
return null;
} public static Section solve2(int[] array, int k) {
int[] sumList = new int[array.length];// 先计算出前0-i个数的和存入sumList
Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
// 记录前i个数的和和值相同的下标
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum = sum + array[i];
sumList[i] = sum;
if (map.containsKey(sum)) {// 将和的下标存入map
List<Integer> indexList = map.get(sum);
indexList.add(i);
} else {
List<Integer> indexList = new ArrayList<Integer>();
indexList.add(i);
map.put(sum, indexList);
}
} boolean find = false;
List<Section> list = new ArrayList<Section>();
for (int j = 0; j < sumList.length; j++) {
int sumi = sumList[j];// 当前遍历的前j个数的和为sumi
if (sumi == k) {// 如果前j个数的和就是k,那么直接为一组解
Section node = new Section(1, (j + 1));
list.add(node);// 加入解集合
find = true;
continue;
}
int temp = sumi + k;// 计算出对应的和已保证a[i]-a[j]=k
if (map.containsKey(temp) && map.get(temp).size() > 0) {
// 如果存在a[i]-a[j]=k,那么从第j+1个数到第i个数之和就为k,这里下标从0开始
int start = j + 2;
int end = -1;
for (Integer integer : map.get(temp)) {// 从和相同的下标中选离j最近比i大的下标作为最后的解
if (integer >= j) {
end = integer + 1;
break;
}
}
if (end >= 0) {
list.add(new Section(start, end));
find = true;
}
}
} if (!find)
System.out.println("No");
else {
Collections.sort(list);// 对可能的解做一次排序,找到符合题意的解
Section section = list.get(0);
System.out.println(section.start + " " + section.end);
return section;
}
return null;
} /**
* 确保List的排序
*
*/
public static class Section implements Comparable<Section> {
int start, end; public Section(int start, int end) {
this.start = start;
this.end = end;
} @Override
public int compareTo(Section o) {
if (this.start == o.start)
return this.end - o.end;
return this.start - o.start;
} } public static void main(String[] args) throws IOException { @SuppressWarnings("deprecation")
StreamTokenizer st = new StreamTokenizer(System.in);
while (st.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int) st.nval;
int[] array = new int[n];
for (int i = 0; i < n; i++) {
st.nextToken();
array[i] = (int) st.nval;
}
st.nextToken();
int k = (int) st.nval;
solve2(array, k);
}
}
}

  其中一开始使用Scanner的方法作为输入,优化许久还是超时,查看其它成功代码采用的是StreamTokenizer方式作为输入。也改为StreamTokenizer方式后,提交通过。

OJ-2:区间问题【九度1554】的更多相关文章

  1. 【九度OJ】题目1065:输出梯形 解题报告

    [九度OJ]题目1065:输出梯形 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1065 题目描述: 每组测试 ...

  2. 【九度OJ】题目1431:Sort 解题报告

    [九度OJ]题目1431:Sort 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1431 题目描述: 给你n个 ...

  3. 九度oj 题目1087:约数的个数

    题目链接:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次输出每个数的约数的个数 输入: 输入的第一行为N,即数组的个数(N<=1 ...

  4. 九度OJ 1502 最大值最小化(JAVA)

    题目1502:最大值最小化(二分答案) 九度OJ Java import java.util.Scanner; public class Main { public static int max(in ...

  5. 九度OJ,题目1089:数字反转

    题目描述: 12翻一下是21,34翻一下是43,12+34是46,46翻一下是64,现在又任意两个正整数,问他们两个数反转的和是否等于两个数的和的反转. 输入: 第一行一个正整数表示测试数据的个数n. ...

  6. 九度OJ 1500 出操队形 -- 动态规划(最长上升子序列)

    题目地址:http://ac.jobdu.com/problem.php?pid=1500 题目描述: 在读高中的时候,每天早上学校都要组织全校的师生进行跑步来锻炼身体,每当出操令吹响时,大家就开始往 ...

  7. 九度OJ 1531 货币面值(网易游戏2013年校园招聘笔试题) -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1531 题目描述: 小虎是游戏中的一个国王,在他管理的国家中发行了很多不同面额的纸币,用这些纸币进行任意的组合可以在 ...

  8. 九度OJ 1024 畅通工程 -- 并查集、贪心算法(最小生成树)

    题目地址:http://ac.jobdu.com/problem.php?pid=1024 题目描述:     省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但 ...

  9. 九度OJ 1371 最小的K个数 -- 堆排序

    题目地址:http://ac.jobdu.com/problem.php?pid=1371 题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4 ...

随机推荐

  1. P4231 三步必杀

    题目描述 问题摘要: N个柱子排成一排,一开始每个柱子损伤度为0. 接下来勇仪会进行M次攻击,每次攻击可以用4个参数l,r,s,e来描述: 表示这次攻击作用范围为第l个到第r个之间所有的柱子(包含l, ...

  2. 草率了,又一个Maven打包的问题

    经常遇到 Maven 相关的问题,这是之前的文章: 这个 Maven 依赖的问题,你敢说你没遇到过:https://mp.weixin.qq.com/s/SzBbDtyRUrk_7LH8SUbGXQ ...

  3. Springboot集成JUnit5优雅进行单元测试

    为什么使用JUnit5 JUnit4被广泛使用,但是许多场景下使用起来语法较为繁琐,JUnit5中支持lambda表达式,语法简单且代码不冗余. JUnit5易扩展,包容性强,可以接入其他的测试引擎. ...

  4. java高级&资深&专家面试题-行走江湖必备-持续更新ing

    行走江湖必备一份面试题,这里给大家整理了一套.0面试官最喜欢问的问题或者出场率较高的面试题,助校招或者社招路上的你一臂之力! 首先我们需要明白一个事实,招聘的一个很关键的因素是在给自己找未来的同事,同 ...

  5. 资源管理神器Clover

    开开心心地上班,这时你得打开我的电脑,点进D盘,打开某个项目;然后还得打开XX文档,还有.... 最后的最后,你的桌面便成了这个样子 每天你都得天打开多个文件夹,切换时找文件找的晕头转向而烦恼. 每天 ...

  6. spring boot:使用caffeine+redis做二级缓存(spring boot 2.3.1)

    一,为什么要使用二级缓存? 我们通常会使用caffeine做本地缓存(或者叫做进程内缓存), 它的优点是速度快,操作方便,缺点是不方便管理,不方便扩展 而通常会使用redis作为分布式缓存, 它的优点 ...

  7. Postgres 10.11安装教程

    Postgres搭建 考虑到Drone和Sonarqube等都需要借助Postgres存储,为了保证CI服务的高效的工作,将考虑独立其中依赖的数据库,避免在繁忙时占用过多资源从而影响整体CI的速度. ...

  8. 第十九章 keepalived高可用

    一.keepalived高可用 1.什么是高可用 一般是指2台机器启动着完全相同的业务系统,当有一台机器down机了,另外一台服务器就能快速的接管,对于访问的用户是无感知的. 2.高可用使用的工具 1 ...

  9. 第一章 Linux操作系统及其历史介绍

    一.什么是操作系统 1.基本含义: 简称OS 是计算机系统中必不可少的基础系统软件,是应用程序运行和用户操作必备的基础环境 操作系统就是一个人与计算机之间的中介 2.组成方式: 操作系统的组成: 计算 ...

  10. Python函数的定义和参数

    函数的初识: 以功能为导向,一个函数就是一个功能.随调随用. 优点: 减少代码重复性. 增强代码的可读性. 函数的结构: def function_name(): 函数体 ​ def: 关键字,定义函 ...