给出一个正整数 N 和长度 L ,找出一段长度大于等于 L 的连续非负整数,他们的和恰好为 N 。答案可能有多个,我我们需要找出长度最小的那个。<br /> 例如 N = 18, L = 2:<br /> 5 + 6 + 7 = 18 <br /> 3 + 4 + 5 + 6 = 18<br />都是满足要求的,但是我们输出更短的 5 6 7 <br />数据范围: 1≤n≤109 , 2≤L≤100
输入描述:
输入数据包括一行: 两个正整数N(1 ≤ N ≤ 1000000000),L(2 ≤ L ≤ 100)
输出描述:
从小到大输出这段连续非负整数,以空格分隔,行末无空格。如果没有这样的序列或者找出的序列长度大于100,则输出No
思路:等差数列
https://www.nowcoder.com/questionTerminal/46eb436eb6564a62b9f972160e1699c9
扩展:和为s的连续正数序列(滑动窗口)
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
输入:target = 9 输出:[[2,3,4],[4,5]]
思路:移动滑动窗口,维护窗口和sum,左开右闭[left,right),sum与target比较移动左右边界
class Solution {
/**
和为s的连续正数序列: 滑动窗口
移动滑动窗口,维护窗口和sum,左开右闭[left,right),sum与target比较移动左右边界
*/
public int[][] findContinuousSequence(int target) {
int left = 1; // 滑动窗口的左边界
int right = 1; // 滑动窗口的右边界
int sum = 0; // 滑动窗口中数字的和
List<int[]> result = new ArrayList<>();
while(left <= target/2){
if(sum < target){ // 右边界向右移动
sum += right;
right++;
}else if(sum > target){ // 左边界向右移动
sum -= left;
left++;
}else{ // 记录结果
int[] res = new int[right - left];
for(int k=left; k < right; k++){
res[k-left] = k;
}
result.add(res);
// 左边界向右移动
sum -= left;
left++;
}
}
return result.toArray(new int[result.size()][]);
}
}
扩展2: 给个范围l-n,一个targer,输出所有和为 target 的个数最少的连续正整数序列(至少含有两个数)
import java.util.*;
/**
和为s的连续正数序列: 滑动窗口
移动滑动窗口,维护窗口和sum,左开右闭[left,right),sum与target比较移动左右边界
*/
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
int len = sc.nextInt();
seq_sum(num,len);
}
public static int seq_sum(int num, int len){
int left = len; // 滑动窗口的左边界
int right = len + 2; // 滑动窗口的右边界
int sum = 2 * len + 1; // 滑动窗口中数字的和
Map<Integer,Integer> map = new HashMap<>();
List<int[]> result = new ArrayList<>();
while(left <= num / 2){
if(sum < num){ // 右边界向右移动
sum += right;
right++;
}else if(sum > num){ // 左边界向右移动
sum -= left;
left++;
}else{ // 记录结果
int[] res = new int[right - left];
for(int k = left; k < right; k++){
res[k-left] = k;
}
result.add(res);
// 左边界向右移动
sum -= left;
left++;
}
}
int xxx[][] = result.toArray(new int[result.size()][]);
if(xxx.length == 0){
System.out.println("No");
return 0;
}
# 求出长度最小的连续正整数序列
#(HashMap记录每个结果序列的长度,求出在二维的下标,使用StringBuilder构建输出)
for(int i = 0; i < result.size(); i++){
map.put(i,xxx[i].length);
}
int minlen = 10000;
for(Integer value : map.values()){ //遍历value求出最小长度
minlen = Math.min(value.intValue(),minlen);
}
int sss = 0;
for(Integer key : map.keySet()){ //遍历key求出value=minlen的key(二维下标)
if(map.get(key.intValue()) == minlen)
sss = key;
}
//构建输出
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < xxx[sss].length; i++) {
stringBuilder.append(xxx[sss][i]);
stringBuilder.append(" ");
}
stringBuilder.deleteCharAt(stringBuilder.length()-1);
System.out.println(stringBuilder.toString());
return 0;
}
}
HashMap便利的四种方式:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* HashMap 不同遍历方法比较
*/
public class TestHashMap {
public static void main(String[] args) {
Map<Integer,String> map =new HashMap<Integer,String>();
map.put(1, "xiao");
map.put(2, "chao");
map.put(3, "shang");
map.put(4, "xue");
//方法一
for(Map.Entry<Integer,String> entry : map.entrySet()) {
System.out.println("方法一:key ="+entry.getKey()+"---value="+entry.getValue());
}
//方法二
for(Integer key:map.keySet()) {
System.out.println("方法二:key = "+key);
}
for(String value:map.values()) {
System.out.println("方法二:value = "+value);
}
//方法三
Iterator<Map.Entry<Integer,String>> entries = map.entrySet().iterator();
while(entries.hasNext()) {
Map.Entry<Integer,String> entry = entries.next();
System.out.println("方法三:key = "+entry.getKey()+"--value="+entry.getValue());
}
//方法四
for(Integer key:map.keySet()) {
String value = map.get(key);
System.out.println("方法四:Key = " + key + ", Value = " + value);
}
}
}