小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列?
数据范围:
进阶:时间复杂度
进阶:时间复杂度
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
9
[[2,3,4],[4,5]]
0
[]
//左神的思路,双指针问题 //当总和小于sum,大指针继续+ //否则小指针+ class Solution { public: vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int> > allRes; int phigh = 2,plow = 1; while(phigh > plow){ int cur = (phigh + plow) * (phigh - plow + 1) / 2; if( cur < sum) phigh++; if( cur == sum){ vector<int> res; for(int i = plow; i<=phigh; i++) res.push_back(i); allRes.push_back(res); plow++; } if(cur > sum) plow++; } return allRes; } };
import java.util.ArrayList; /* *初始化small=1,big=2; *small到big序列和小于sum,big++;大于sum,small++; *当small增加到(1+sum)/2是停止 */ public class Solution { public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> lists=new ArrayList<ArrayList<Integer>>(); if(sum<=1){return lists;} int small=1; int big=2; while(small!=(1+sum)/2){ //当small==(1+sum)/2的时候停止 int curSum=sumOfList(small,big); if(curSum==sum){ ArrayList<Integer> list=new ArrayList<Integer>(); for(int i=small;i<=big;i++){ list.add(i); } lists.add(list); small++;big++; }else if(curSum<sum){ big++; }else{ small++; } } return lists; } public int sumOfList(int head,int leap){ //计算当前序列的和 int sum=head; for(int i=head+1;i<=leap;i++){ sum+=i; } return sum; } }
# -*- coding:utf-8 -*-
class Solution:
def FindContinuousSequence(self, tsum):
# write code here
res=[]
for i in range(1,tsum//2+1):
sumRes=i
for j in range(i+1,tsum//2+2):
sumRes+=j
if sumRes==tsum:
res.append(list(range(i,j+1)))
break
elif sumRes>tsum:
break
return res
/* 用两个数字begin和end分别表示序列的最大值和最小值, 首先将begin初始化为1,end初始化为2. 如果从begin到end的和大于s,我们就从序列中去掉较小的值(即增大begin), 相反,只需要增大end。 终止条件为:一直增加begin到(1+sum)/2并且end小于sum为止 */class Solution { public: vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int> > res; if(sum < 3) return res; int mid = (sum + 1)>>1; int begin = 1; int end = 2; int cur = begin + end; while(begin < mid && end < sum) { while(cur > sum) { cur -= begin; begin++; } if(cur == sum) InsertRes(begin,end,res); end++; cur += end; } return res; } void InsertRes(int begin,int end,vector<vector<int> > &res) { vector<int> temp; for(int i = begin;i<=end;i++) temp.push_back(i); res.push_back(temp); } };
# -*- coding:utf-8 -*- class Solution: def FindContinuousSequence(self, tsum): if tsum < 3: return [] res = [] small = 1 big = 2 mid = (1 + tsum) / 2 curSum = small + big while small < mid: if curSum == tsum: res.append(range(small, big + 1)) small += 2 big += 1 curSum -= small * 2 - 3 curSum += big elif curSum < tsum: big += 1 curSum += big else: curSum -= small small += 1 return res
public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>(); if (sum < 3) return listAll; int small = 1; int big = 2; int middle = (sum + 1) / 2; int curSum = 3; while (small < middle) { while (curSum < sum) { big++; curSum += big; } if (curSum == sum) { ArrayList<Integer> list = new ArrayList<>(); for (int i = small; i <= big; i++) { list.add(i); } listAll.add(list); } curSum -= small; small++; } return listAll; }
typedef vector<int> vi; typedef vector<vi> vvi; class Solution { public: vvi FindContinuousSequence(int sum) { vvi res; sum <<= 1; for(int i = 2; i * i <= sum; ++i) if(sum % i == 0){ int j = sum / i, t = (j - i + 1); if(!(t & 1)){ res.push_back(vi()); vi& v = res[res.size() - 1]; t >>= 1; for(int a = t; a <= j - t; ++a) v.push_back(a); } } for(int i = 0, j = int(res.size()) - 1; i < j; ++i, --j) swap(res[i], res[j]); return res; } };
//我竟然解了二元一次方程,我是菜鸟我怕谁。。 //(start+end)*(end-start+1)/2=sum; //根据start解出end。。。。。 public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> result=new ArrayList<ArrayList<Integer>>(); if(sum<3) return result; for(int i=1;i<=sum/2;i++){ int value=1+4*i*i-4*i+8*sum; int valueSqrt=(int)Math.sqrt(value); if(value>=25&&valueSqrt*valueSqrt==value){ ArrayList<Integer> path=new ArrayList<Integer>(); for(int j=i;j<=(valueSqrt-1)>>1;j++) path.add(j); result.add(path); } } return result; }
# Python 感觉比较简短的代码了 class Solution: def FindContinuousSequence(self, tsum): # write code here l, r, sum, res = 1, 2, 3, [] while l<r: if sum>tsum: sum -= l l += 1 else: if sum==tsum: res.append([i for i in range(l,r+1)]) r += 1 sum += r return res
等差数列求和直接公式算
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<int> tmp;
vector<vector<int> > ans;
for(int i = 1; i < sum; i++){
double b = (sqrt(4*i*i-4*i+8*sum+1) - 1.0)/2.0;
int b_int = floor(b + 0.5);
if(abs(b - b_int) < 1e-3){
for(int j = i; j <= b_int; j++) tmp.push_back(j);
ans.push_back(tmp);
tmp.clear();
}
}
return ans;
}
};
def FindContinuousSequence(self, tsum): if tsum < 3: return [] res, arr = [], [1, 2] middle = tsum // 2 + 1 while arr and arr[0] < middle: if sum(arr) < tsum: arr.append(arr[-1] + 1) elif sum(arr) > tsum: arr.pop(0) else: res.append([i for i in arr]) arr.append(arr[-1] + 1) arr.pop(0) if not arr: return [] return res
import java.util.ArrayList;
/**
* 题目描述
* 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。
* 但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。
* 没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。
* 现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
* 输出描述:
* 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
*
* @author shijiacheng
*/
public class FindContinuousSequenceSolution {
public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if (sum < 3){
return result;
}
int small = 1;
int big = 2;
int curSum = small +big;
int middle = (sum+1)/2;
while (small<middle){
if (curSum == sum){
ArrayList<Integer> temp = new ArrayList<>();
for (int i = small; i <= big; i++) {
temp.add(i);
}
result.add(temp);
}
while (curSum > sum && small<middle){
curSum -= small;
small++;
if (curSum == sum){
ArrayList<Integer> temp = new ArrayList<>();
for (int i = small; i <= big; i++) {
temp.add(i);
}
result.add(temp);
}
}
big++;
curSum += big;
}
return result;
}
}
class Solution { public: vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int>> res; if(sum<3) return res; int begin = 1; int end = 2; //初始化curSum时直接用3,不要用a+b,这样效率会高一点 int curSum = 3; int mid = (1+sum)>>1; //当begin<mid或者end<(mid+1)时,连续序列的和肯定超出sum了,所以这两个都要限制一下 while(begin<mid && end<mid+1){ while(curSum>sum){ curSum -= begin; ++begin; } //这段代码不要上一个while之前,不然会代码重复,而且多了一次判断,效率不高 if(curSum==sum) insertRes(begin,end,res); ++end; curSum += end; } return res; } private: void insertRes(int a,int b,vector<vector<int>> &res){ vector<int> temp; for(int i=a;i<=b;++i) temp.push_back(i); res.push_back(temp); } };
import java.util.ArrayList; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer> > alal = new ArrayList<ArrayList<Integer> >(); for(int i = 1; i <= sum/2; i++){ ArrayList<Integer> al = new ArrayList<>(); int tempSum = i; int nextNum = i; al.add(i); while(tempSum < sum){ nextNum++; al.add(nextNum); if((tempSum += nextNum) == sum){ alal.add(al); break; } } } return alal; } }
import java.util.ArrayList; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> ans = new ArrayList<>(); for (int n = (int) Math.sqrt(2 * sum); n >= 2; n--) { if ((n & 1) == 1 && sum % n == 0 || (sum % n) * 2 == n) { ArrayList<Integer> list = new ArrayList<>(); for (int j = 0, k = (sum / n) - (n - 1) / 2; j < n; j++, k++) { list.add(k); } ans.add(list); } } return ans; } }
/* 直接用数学方法做的 等差数列公式 2*n*a1+n(n-1)/2 = s; 由n>= 2 得 a1 <= (s - 1)/2 对首位数字a1从1到 (s - 1)/2遍历 等差数列公式变形 n*n+(2*a1 - 1)n-2s = 0 可得 n = [-(2a - 1) + sqrt((2a - 1) * (2a - 1) + 8s)]/2 检验n是否为整数,是则得到一个答案 */ vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int> > ans; int maxA1 = (sum - 1) / 2; //sum = n*a1 + n(n-1)/2 n最小为2 推导得到 for(int i = 1; i <= maxA1; i++) //首位数字遍历 { double f = (sqrt(double((2 * i - 1) * (2 * i - 1) + 8 * sum)) + 1 - 2 * i) / 2; //计算长度 int n = int(f); if(abs(f - n) < 0.000001) //长度是整数,有效 { vector<int> tempans; for(int j = 0; j < n; j++) tempans.push_back(i + j); ans.push_back(tempans); } } return ans; }
/*LinkedList.add复杂度低,所以用了LinkedList*/ public class Solution { public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> resultList = new ArrayList<ArrayList<Integer>>(); if(sum <= 2){ return resultList; } for(int start = 1;start <= (sum-1)/2; start++){ int end = start+1; int seqSum = (start+end)*(end-start+1)/2; LinkedList<Integer> result = new LinkedList<Integer>(); result.add(start); while(seqSum <= sum){ result.add(end); if(seqSum == sum){ resultList.add(new ArrayList<Integer>(result)); break; } end++; seqSum = (start+end)*(end-start+1)/2; } } return resultList; } }
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer> > lists = new ArrayList<ArrayList<Integer> >(); for(int k = 2; k*k < 2*sum; k++){ double m = ((2.0*sum)/k-k+1)/2.0; int temp = (int)m; if(m == temp){ ArrayList<Integer> list = new ArrayList<Integer>(); for(int i = 0; i < k; i++){ list.add(i+temp); } lists.add(0, list); } } return lists; } public ArrayList<ArrayList<Integer> > FindContinuousSequence_(int sum) { ArrayList<ArrayList<Integer> > Lists = new ArrayList<ArrayList<Integer> >(); for(int i = 2; i <= sum/2+1; i++){ if(i%2 == 1){ if(sum%i == 0){ int temp = sum/i; if(temp-i/2 > 0){ ArrayList<Integer> tempList = new ArrayList<Integer>(); for(int j = temp-i/2; j <= temp+i/2; j++){ tempList.add(j); } Lists.add(0,tempList); } } }else{ int temp = sum/i; double temp1 = temp+0.5; if((int)(temp1 * i) == sum){ if(temp-i/2+1 > 0){ ArrayList<Integer> tempList = new ArrayList<Integer>(); for(int j = temp-i/2+1; j <= temp+i/2; j++){ tempList.add(j); } Lists.add(0,tempList); } } } } return Lists; }