题解 | #和为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);