当前位置:网站首页>回溯——491. 递增子序列
回溯——491. 递增子序列
2022-07-26 12:13:00 【向着百万年薪努力的小赵】
1 题目描述
给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。
数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/increasing-subsequences
2 题目示例
示例 1:
输入:nums = [4,6,7,7]
输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
示例 2:
输入:nums = [4,4,3,2,1]
输出:[[4,4]]
3 题目提示
1 <= nums.length <= 15
-100 <= nums[i] <= 100
4 思路
可以用递归的方法实现二进制枚举,枚举出所有的子序列,然后判断是否合法。,我们可以得到这样的代码:
List<List<Integer>> ans = new ArrayList<List<Integer>>();
List<Integer> temp = new ArrayList<Integer>();
public void dfs(int cur, int[] nums) {
if (cur == nums.length) {
// 判断是否合法,如果合法判断是否重复,将满足条件的加入答案
if (isValid() && notVisited()) {
ans.add(new ArrayList<Integer>(temp));
}
return;
}
// 如果选择当前元素
temp.add(nums[cur]);
dfs(cur + 1, nums);
temp.remove(temp.size() - 1);
// 如果不选择当前元素
dfs(cur + 1, nums);
}
这是一个递归枚举子序列的通用模板,即用一个临时数组temp来保存当前选出的子序列,使用cur来表示当前位置的下标,在dfs(cur,nums)开始之前,[0, cur ―1]这个区间内的所有元素都已经被考虑过,而[cur, n]这个区间内的元素还未被考虑。在执行dfs(cur,nums)时,我们考虑cur这个位置选或者不选,如果选择当前元素,那么把当前元素加入到temp中,然后递归下一个位置,在递归结束后,应当把temp 的最后一个元素删除进行回溯;如果不选当前的元素,直接递归下一个位置。当然,如果我们简单地这样枚举,对于每一个子序列,我们还需要做一次O(n)的合法性检查和哈希判重复,在执行整个程序的过程中,我们还需要使用一个空间代价O(2")的哈希表来维护已经出现的子序列的哈希值。我们可以对选择和不选择做一些简单的限定,就可以让枚举出来的都是合法的并且不重复:
使序列合法的办法非常简单,即给「选择」做一个限定条件,只有当前的元素大于等于上一个选择的元素的时候才能选择这个元素,这样枚举出来的所有元素都是合法的
那如何保证没有重复呢?我们需要给「不选择」做一个限定条件,只有当当前的元素不等于上一个选择的元素的时候,才考虑不选择当前元素,直接递归后面的元素。因为如果有两个相同的元素,我们会考虑这样四种情况:
- 前者被选择,后者被选择
- 前者被选择,后者不被选择
- 前者不被选择,后者被选择
- 前者不被选择,后者不被选择
其中第二种情况和第三种情况其实是等价的,我们这样限制之后,舍弃了第二种,保留了第三种,于是达到了去重的目的。
复杂度分析
- 时间复杂度:o(2n*n)。仍然需要对子序列做二进制枚举,枚举出的序列虽然省去了判断合法性和哈希的过程,但是仍然需要O(n)的时间添加到答案中。
- 空间复杂度:O(n)。这里临时数组的空间代价是O(n),递归使用的栈空间的空间代价也是O(n)。
5 我的答案
class Solution {
List<Integer> temp = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> findSubsequences(int[] nums) {
dfs(0, Integer.MIN_VALUE, nums);
return ans;
}
public void dfs(int cur, int last, int[] nums) {
if (cur == nums.length) {
if (temp.size() >= 2) {
ans.add(new ArrayList<Integer>(temp));
}
return;
}
if (nums[cur] >= last) {
temp.add(nums[cur]);
dfs(cur + 1, nums[cur], nums);
temp.remove(temp.size() - 1);
}
if (nums[cur] != last) {
dfs(cur + 1, last, nums);
}
}
}
边栏推荐
猜你喜欢

Ssj-21b time relay

连锁店收银系统如何帮助鞋店管理好分店?

结合环境光、接近传感以及红外测距的光距感芯片4530A

空洞卷积详解(输入输出大小分析)

使用fastJson中的JSONObject对象简化POST请求传参

El form displays two columns per row, with the bottom button centered

Why BGP server is used in sunflower remote control? Automatic optimal route and high-speed transmission across operators

DS-112时间继电器

微软关闭了两种攻击途径:Office 宏、RDP 暴力破解

基于STM32的SIM900A发送中文和英文短信
随机推荐
2、 Container_
以太网驱动详解之RMII、SMII、GMII、RGMII接口
DS-24C/DC220V时间继电器
MATLAB中strjoin函数使用
.eslintrc.js configuration description
[map] universal map usage & two ways of fuzzy query
扫雷小游戏——轻松玩上瘾(C语言版)
transformer一统天下?depth-wise conv有话要说
Redis主从复制原理
[MySQL constraint]
Pytest interface automation test framework | rerun failed cases
pytest接口自动化测试框架 | pytest获取执行数据、pytest禁用插件
三维点云课程(八)——特征点匹配
Use of strjoin function in MATLAB
Yuancosmos daily | yuancosmos social app "Party Island" product off the shelves; Guangzhou Nansha yuanuniverse industrial agglomeration zone was unveiled; The inter ministerial joint conference system
大佬们,请教一下,我按照文档配了cdc连接oracle,总是运行报错找不到类 ValidstionE
QT入门引导 及其 案例讲解
HTAP是有代价的
3D point cloud course (VIII) -- feature point matching
Oracle AWR report script: SQL ordered by elapsed time