小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列?
数据范围:
进阶:时间复杂度)
进阶:时间复杂度
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
9
[[2,3,4],[4,5]]
0
[]
# -*- coding:utf-8 -*- class Solution: def FindContinuousSequence(self, tsum): # write code here if tsum <= 0: return [] if tsum == 2: return [] if tsum == 3: return [[1,2]] e = tsum//2 res = [] sums = 0 for i in range(2, e): temp = [] sums = 0 if i % 2 == 0: k = tsum // i m = i // 2 if tsum % i == 0: continue else: if k-m+1 <=0: continue for j in range(k-m+1, k+m+1): sums += j temp.append(j) if sums == tsum: res.append(temp) temp = [] sums = 0 elif i % 2 != 0: k = tsum // i m = i // 2 if tsum % i != 0: continue else: if k-m <= 0: continue for j in range(k-m, k+m+1): sums += j temp.append(j) if sums == tsum: res.append(temp) return sorted(res)
//左神的思路,双指针问题
//当总和小于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;
}
import java.util.ArrayList; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { //存放结果 ArrayList<ArrayList<Integer> > result = new ArrayList<>(); //两个起点,相当于动态窗口的两边,根据其窗口内的值的和来确定窗口的位置和大小 int plow = 1,phigh = 2; while(phigh > plow){ //由于是连续的,差为1的一个序列,那么求和公式是(a0+an)*n/2 int cur = (phigh + plow) * (phigh - plow + 1) / 2; //相等,那么就将窗口范围的所有数添加进结果集 if(cur == sum){ ArrayList<Integer> list = new ArrayList<>(); for(int i=plow;i<=phigh;i++){ list.add(i); } result.add(list); plow++; //如果当前窗口内的值之和小于sum,那么右边窗口右移一下 }else if(cur < sum){ phigh++; }else{ //如果当前窗口内的值之和大于sum,那么左边窗口右移一下 plow++; } } return result; } }