剑指offer——和为S的连续正数序列
笨方法:从1开始向后遍历,同时记下当前数组中的和,若和为sum,则将当前数组的值存入结果集中res.add(s),此时要重新 s = new ArrayList<>(),
不然后面改变 s 之后,res中的结果也会发生变化。
同时用一个下标记录下当前遍历的数组中的最小值,在 s new之后,重新拷贝过去。
也可以换一种思路,就是将此时的结果写作一个方法,每次都重新调用。
import java.util.ArrayList; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> res = new ArrayList<>(); if(sum == 0 || sum == 1 || sum == 2) return res; ArrayList<Integer> s = new ArrayList<>(); int listSum = 0; int i = 1; int low = 1; while(i < sum){ if(listSum < sum){ listSum += i; s.add(i++); } if(listSum >= sum){ if(listSum == sum){ res.add(s); s = new ArrayList<>( ); for(int j = low; j < i; j++){ s.add( j ); } } listSum -= s.get(0); s.remove(0); low++; } } return res; } }
别人的方法:因为是连续正整数,所以可以利用等差数列的求和公式来计算ss
同时,有高位和低位两个指针,指向连续正整数的高低位,ss == sum时,就将其数组加入到res结果集中,当ss<sum时,高位指针++,当ss> sum时,低位指针++
import java.util.ArrayList; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> res = new ArrayList<>(); if(sum == 0 || sum == 1 || sum == 2) return res; int left = 1; int right = 2; while(right < sum && left < right){ int s = ((right + left) * (right - left + 1)) >> 1; if(s == sum){ int temp = left; ArrayList<Integer> r = new ArrayList<>(); while(temp <= right){ r.add(temp++); } res.add(r); left++; } else if(s < sum){ right++; } else{ left++; } } return res; } }