题解 | #和为S的连续正数序列# 数学方法O(S),80.14%
和为S的连续正数序列
http://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe
(2 * start + n - 1) * n / 2 = sum其中,sum为和,start为首项,n为项数
可以得到2 * sum >= n^2 + n > n^2 所以 n < sqrt(2 * sum)
因此从2(因为至少两项)遍历到sqrt(2*sum)即可
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > ans = new ArrayList();
// (2s+n-1)*n = 2sum >= n^2+n >n^2
// 所以,n < sqrt(2sum)
int maxBound = (int)Math.ceil(Math.sqrt(2 * sum));
// 至少包含两个数,因此n(即i)至少为2
// n从后向前遍历符合首项从小到大的要求(n越大,首项越小)
for (int i = maxBound - 1; i >= 2 ; i--) {
// 查看是否能够整除
if (2*sum%i!=0) {
continue;
}
if ((2*sum/i+1-i)%2!=0) {
continue;
}
// 找到了满足的列表
int start = (2*sum/i+1-i)/2;
ArrayList list = new ArrayList();
for (int j = 0; j < i; j++) {
list.add(start+j);
}
ans.add(list);
}
return ans;
}
} 为什么不是O(根号S)? 因为最外层虽然是根号S,但是创建res列表时候又遍历了一遍,也是根号S,注意这段代码
// 找到了满足的列表
int start = (2*sum/i+1-i)/2;
ArrayList list = new ArrayList();
for (int j = 0; j < i; j++) {
list.add(start+j);
}
ans.add(list); 
查看20道真题和解析