题目描述
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例
输入:target = 9
输出:[[2,3,4],[4,5]]
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
解题思路
因为我们要寻找的是一个连续递增的序列,所以可以利用等差数列求和的方式计算某一段序列的值。
故我们只需要找到一段序列的两端的数字就可以确定这个序列。
为了找到这两个点,可以使用二重循环来计算。因为这是一个递增序列,所以可以使用二分查找对二重循环进行优化。
最外层循环确定左端点的位置,然后在左端点的右侧进行二分查找,寻找右端点。最后将满足的序列添加进返回值中。
class Solution {
public int[][] findContinuousSequence(int target) {
List<int[]> list = new ArrayList<>();
for (int i = 1; i <= target / 2 + 1; i++) {
int nextPos = binSearch57(target, i, i + 1, target / 2 + 1);
if (nextPos != -1) {
//添加进result
int[] temp = new int[nextPos - i + 1];
for(int j = 0;j<nextPos-i+1;j++){
temp[j] = i+j;
}
list.add(temp);
}
}
return list.toArray(new int[list.size()][]);
}
private int binSearch57(int target, int prePos, int l, int r) {
int left = l, right = r;
while (left <= right) {
int mid = (left + right) >> 1;
//计算等差数列的和
int sum = (prePos + mid) * (mid - prePos + 1) >> 1;
if (sum == target) {
return mid;
} else if (sum > target) {
right = mid - 1;
}else{
left = mid + 1;
}
}
return -1;
}
}