题目描述:
题号:78
解题思路:
思路一:回溯
回溯是什么?
回溯算法(Backtracking Algorithm)是一种通过尝试不同的选择并逐步构建解决方案,以解决问题的方法。如果在某个步骤发现当前选择无法构成有效的解决方案,则算法会“回溯”到上一步,尝试其他选择。这种方法通常用于解决那些可以分解为多个子问题,并且需要找到所有或某些满足特定条件的解的问题。
回溯算法通常涉及以下步骤:
-
选择:在当前状态下选择一个选项进行尝试。
-
约束检查:检查当前选择是否满足问题的约束条件。
-
进一步探索:如果当前选择满足条件,则继续在下一个状态进行选择,即递归地调用自身。
-
撤销选择:如果当前选择无法构成有效解或所有可能的选择都已尝试,则撤销该选择,回溯到上一步,尝试其他选项。
-
结束条件:当找到一个完整且有效的解决方案,或确定没有更多可能的方案时,结束算法。
本题关键点:逐个递归,将每个元素都包含一遍。不能重复,一次每次都输入 i + 1 作为下一次递归的起点
时间复杂度:O(N * 2 ^ N)
空间复杂度:O(N)
C++
// C++
class Solution {
vector<int> temp;
vector<vector<int>> answer;
void backTrace(vector<int>& nums, int index) {
answer.push_back(temp);
for(int i = index; i < nums.size(); i++) {
temp.push_back(nums[i]);
backTrace(nums, i + 1);
temp.pop_back();
}
}
public:
vector<vector<int>> subsets(vector<int>& nums) {
if(nums.size() == 0) {
return {};
}
backTrace(nums, 0);
return answer;
}
};
go
// go
func subsets(nums []int) [][]int {
if len(nums) == 0 {
return nil
}
temp := []int{}
answer := [][]int{}
var backTrace func(int)
backTrace = func(index int) {
answer = append(answer, slices.Clone(temp))
for i := index; i < len(nums); i++ {
temp = append(temp, nums[i])
backTrace(i + 1)
temp = temp[:len(temp) - 1]
}
}
backTrace(0)
return answer
}