求解Combination Sum:为何题解中需使用currArr.pop()?
currArr.pop()在这个Combination Sum解法里是必需的? 嘿,这个问题其实戳中了回溯算法最核心的「状态重置」逻辑,我给你一步步掰扯清楚~
首先得明确这段代码的核心思路:它用回溯算法来枚举所有可能的候选元素组合,currArr是用来临时存储当前正在构建的组合的数组。我们一步步看push和pop的配合:
1. push的作用:构建当前分支的组合
当我们判断target >= candidates[i]时,说明这个元素可以加入当前组合,于是执行currArr.push(candidates[i]),然后递归调用innerFunction去探索添加这个元素之后的所有可能组合(比如加入2之后,继续尝试加2、3、6、7来凑剩余的target)。
2. pop的作用:回溯时重置状态,不干扰其他分支
当递归函数返回时,意味着以当前元素开头的所有组合都已经探索完毕了。这时候必须执行currArr.pop(),把刚才加进去的元素从临时数组里移除——这就是回溯的「回」,把状态恢复到添加这个元素之前的样子,这样才能回到上一步,尝试下一个候选元素。
举个实际的例子(用你的输入[2,3,6,7],target=7):
- 第一次循环选元素2,
currArr变成[2],递归探索剩余target=5的组合; - 在递归里再选2,
currArr变成[2,2],递归探索剩余target=3的组合; - 再选2,
currArr变成[2,2,2],剩余target=1,这时候所有候选元素都比1大,递归返回; - 这时候执行
pop(),currArr变回[2,2],接下来尝试下一个元素3:push3后currArr是[2,2,3],剩余target=0,这个组合符合条件,被加入结果; - 递归返回后,再次执行
pop(),currArr变回[2,2],继续尝试下一个元素6,发现6>3,直接返回; - 回到上一层,执行
pop(),currArr变回[2],接下来尝试元素3,继续探索新的组合...
如果没有pop()会发生什么?
假设去掉pop(),当我们探索完[2,2,3]之后,currArr会一直保留[2,2,3],接下来尝试下一个元素时,就会往里面继续加元素,变成[2,2,3,3]这种完全错误的组合——因为我们已经处理完[2,2,3]这个分支了,需要回到[2,2]的状态去尝试其他可能,而pop()就是干这个“清理现场”的活。
总结
currArr.pop()是回溯算法中状态重置的关键步骤:它确保每次递归返回后,临时组合数组回到添加当前元素之前的状态,让后续的分支探索不会被之前的组合残留元素干扰,从而能正确枚举所有符合条件的不重复组合(这里的不重复是通过index参数控制只能从当前及之后的元素选择,再配合pop()实现的)。
内容的提问来源于stack exchange,提问作者sop ian

