【剑指offer】74.和为S的连续正数序列
总目录:
1.问题描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列?
 数据范围:0<n≤100
 进阶:时间复杂度 O(n)
2.问题分析
用等差数列的求和公式,只是差固定为1
1滑动窗口法
用一个窗口进行滑动,窗口内和小于目标值则右边界+1,窗口内和大于目标值则左边界+1,等于目标值时则把窗口内的序列保存下来然后左边界+1
2抓中间数法
假设目标值tgtVal可以分为n项之和,n取值范围为[2-tgtVal],tgtVal/n就是序列中间项的和,只需要区分以下n是奇数还是偶数即可得到该序列,通过等差数列求和公式计算序列和然后与目标值进行比较。
3.代码实例
滑动窗口法
 
1 import java.util.ArrayList; 2 public class Solution { 3 public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { 4 //存放结果 5 ArrayList<ArrayList<Integer> > result = new ArrayList<>(); 6 //两个起点,相当于动态窗口的两边,根据其窗口内的值的和来确定窗口的位置和大小 7 int plow = 1,phigh = 2; 8 while(phigh > plow){ 9 //由于是连续的,差为1的一个序列,那么求和公式是(a0+an)*n/2 10 int cur = (phigh + plow) * (phigh - plow + 1) / 2; 11 //相等,那么就将窗口范围的所有数添加进结果集 12 if(cur == sum){ 13 ArrayList<Integer> list = new ArrayList<>(); 14 for(int i=plow;i<=phigh;i++){ 15 list.add(i); 16 } 17 result.add(list); 18 plow++; 19 //如果当前窗口内的值之和小于sum,那么右边窗口右移一下 20 }else if(cur < sum){ 21 phigh++; 22 }else{ 23 //如果当前窗口内的值之和大于sum,那么左边窗口右移一下 24 plow++; 25 } 26 } 27 return result; 28 } 29 }
抓中间数法
 
1 class Solution { 2 public: 3 void addVec(vector<vector<int>>& vec, int start, int end) { 4 if (start > end) { 5 return; 6 } 7 8 vector<int> newVec; 9 for (int i = start; i <= end; i++) { 10 newVec.push_back(i); 11 } 12 13 vec.push_back(newVec); 14 } 15 16 vector<vector<int>> FindContinuousSequence(int sum) { 17 vector<vector<int>> ret; 18 if (sum <= 0) { 19 return ret; 20 } 21 22 //不算1等分的情况 23 //ret.push_back(vector<int>(1, sum)); 24 25 int midVal = 0; 26 int start = 0, end = 0; 27 //试图将sum分为i份 28 for (int i = sum; i > 1; i--) { 29 midVal = sum / i; 30 31 //如果进行偶数等分 32 if ((i % 2) == 0) { 33 //计算首尾 34 start = midVal + 1 - i / 2; 35 end = midVal + i / 2; 36 if (start <= 0) { 37 continue; 38 } 39 40 //验证序列和 41 if (((start + end)*i / 2) == sum) { 42 addVec(ret, start, end); 43 } 44 } else { //奇数等分midva 45 //计算首尾 46 start = midVal - i / 2; 47 end = midVal + i / 2; 48 if (start <= 0) { 49 continue; 50 } 51 52 //验证序列和 53 if ((midVal * i) == sum) { 54 addVec(ret, start, end); 55 } 56 } 57 } 58 59 60 return ret; 61 } 62 };
 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号