网站救助计划
1.为阅读体验,本站无任何广告,也无任何盈利方法,站长一直在用爱发电,现濒临倒闭,希望有能力的同学能帮忙分担服务器成本
2.捐助10元及以上同学,可添加站长微信lurenzhang888,备注捐助,网站倒闭后可联系站长领取本站pdf内容
3.若网站能存活下来,后续将会持续更新内容
题目描述
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
限制:
- 1 <= target <= 10^5
题解 1
(双指针算法) O(n)
最容易想到的是用两重循环去枚举和为 S 的序列,时间复杂度是 O(n^2) 我们可以使用双指针算法进行优化,用两个指针 i, j 指向当前正在枚举的序列的起点和终点
- 当 i \sim j 之间的和小于 S 时, j 指针往后移
- 当 i \sim j 之间的和等于 S 时,记录当前序列,加入到答案中
- 当 i \sim j 之间的和大于 S 时,i 指针往后移
可以 i 和 j 是单调的,不会走回头路,且当 i 往后移时 j 不会往前移
时间复杂度
i 和 j 最终都从 1 走到 target,时间复杂度为 O(n)
空间复杂度
O(n)
C++ 代码
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> res;
vector<int> path;
for (int i = 1, j = 1, sum = 0; i < target; i ++ ) {
while (j < target && sum < target) sum += j, j ++ ;
if (sum == target) {
for (int k = i; k < j; k ++ ) path.push_back(k);
res.push_back(path);
path.clear();
}
sum -= i;
}
return res;
}
};
Java 代码
class Solution {
public int[][] findContinuousSequence(int target) {
List<int[]> res = new ArrayList<>();
for (int i = 1, j = 1, sum = 0; i < target; i ++ ) {
while (j < target && sum < target) {
sum += j;
j ++ ;
}
if (sum == target) {
int[] path = new int[j - i];
for (int k = i; k < j; k ++ ) {
path[k - i] = k;
}
res.add(path);
}
sum -= i;
}
return res.toArray(new int[res.size()][]);
}
}
Python 代码
class Solution:
def findContinuousSequence(self, target: int) -> List[List[int]]:
res = []
path = []
i, j, s = 1, 1, 0
while i < target:
while j < target and s < target:
s += j
j += 1
if s == target:
path = list(range(i, j))
res.append(path[:])
path.clear()
s -= i
i += 1
return res
题解 2
(回溯)
将每个数作为起点开始找合法方案并记录路径和,如果 sum == target,则将路径加入答案中。
剪枝优化:
- 如果和 sum > target 说明不是一个合法方案,直接返回。
- 如果当前正在遍历的数和路径中的最后一个数不是相邻的,也不是一个合法方案,直接 break 结束当前搜索分支。
时间复杂度
回溯的时间复杂度一般是指数级别的,由于这道题目合法方案数比较少,可以过。
空间复杂度
O(n)
C++ 代码
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void dfs(int start, int sum, int target) {
if (sum > target) return;
if (start == target) return;
if (sum == target) {
res.push_back(path);
return;
}
for (int i = start; i < target; i ++ ) {
if (path.size() && path.back() + 1 != i) break;
path.push_back(i);
dfs(i + 1, sum + i, target);
path.pop_back();
}
}
vector<vector<int>> findContinuousSequence(int target) {
dfs(1, 0, target);
return res;
}
};
Java 代码
class Solution {
List<int[]> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
void dfs(int start, int sum, int target) {
if (sum > target || start == target) {
return;
}
if (sum == target) {
int[] pathArray = new int[path.size()];
for (int i = 0; i < path.size(); i ++ ) {
pathArray[i] = path.get(i);
}
res.add(pathArray);
return;
}
for (int i = start; i < target; i ++ ) {
if (!path.isEmpty() && path.get(path.size() - 1) + 1 != i) {
break;
}
path.add(i);
dfs(i + 1, sum + i, target);
path.remove(path.size() - 1);
}
}
int[][] findContinuousSequence(int target) {
dfs(1, 0, target);
int[][] result = new int[res.size()][];
for (int i = 0; i < res.size(); i++) {
result[i] = res.get(i);
}
return result;
}
}
Python 代码
class Solution:
def findContinuousSequence(self, target: int) -> List[List[int]]:
res = []
path = []
def dfs(start, total, target):
if total > target or start == target:
return
if total == target:
res.append(path[:])
return
for i in range(start, target):
if path and path[-1] + 1 != i:
break
path.append(i)
dfs(i + 1, total + i, target)
path.pop()
dfs(1, 0, target)
return res
本文由读者提供,Github地址:https://github.com/tonngw
点击面试手册,获取本站面试手册PDF完整版