LeetCode回溯算法子序列问题——491. 递增子序列

た 入场券 2023-09-28 15:54 145阅读 0赞

一、题目描述:

491. 递增子序列

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况

a682fc7a710046b68522332da2af0341.png

二、分析

1.本题是一个经典的回溯算法题目,怎么辨别题解需要使用回溯算法呢?

回溯法,一般可以解决如下几种问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 棋盘问题:N皇后,解数独等等

2.回溯法模板

回溯三部曲:

(1)返回值以及参数

返回值一般为void。再来看一下参数,因为回溯算法需要的参数可不像二叉树递归的时候那么容易一次性确定下来,所以一般是先写逻辑,然后需要什么参数,就填什么参数

(2)回溯函数终止条件

什么时候达到了终止条件,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归

(3)回溯搜索的遍历过程。

for循环是横向遍历可以理解一个节点有多少个孩子,这个for循环就执行多少次

backtracking(递归)就是纵向遍历,这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。

总结回溯算法模板如下:

  1. void backtracking(参数) {
  2. if (终止条件) {
  3. 存放结果;
  4. return;
  5. }
  6. for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
  7. 处理节点;
  8. backtracking(路径,选择列表); // 递归
  9. 回溯,撤销处理结果
  10. }
  11. }

3.代码

  1. class Solution {
  2. List<Integer> temp = new ArrayList<Integer>();
  3. List<List<Integer>> ans = new ArrayList<List<Integer>>();
  4. public List<List<Integer>> findSubsequences(int[] nums) {
  5. dfs(0, Integer.MIN_VALUE, nums);
  6. return ans;
  7. }
  8. public void dfs(int cur, int last, int[] nums) {
  9. if (cur == nums.length) {
  10. if (temp.size() >= 2) {
  11. ans.add(new ArrayList<Integer>(temp));
  12. }
  13. return;
  14. }
  15. if (nums[cur] >= last) {
  16. temp.add(nums[cur]);
  17. dfs(cur + 1, nums[cur], nums);
  18. temp.remove(temp.size() - 1);
  19. }
  20. if (nums[cur] != last) {
  21. dfs(cur + 1, last, nums);
  22. }
  23. }
  24. }

发表评论

表情:
评论列表 (有 0 条评论,145人围观)

还没有评论,来说两句吧...

相关阅读