题目链接:
https://leetcode-cn.com/problems/increasing-subsequences/
难度:中等
491. 递增子序列
给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。
示例:
输入: [4, 6, 7, 7]
输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
说明:
给定数组的长度不会超过15。
数组中的整数范围是 [-100,100]。
给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。
要死了 头疼 牙疼 喉咙不舒服 。。。。 日啊 不会做 也不想做了 直接看答案吧,,,
第一种方法挺好理解的
枚举 共有 2的n次方种情况 全部枚举一次 判断是否为递增子序列即可 当然还要判断是否重复(这个地方不太懂)
使用二进制记录可能的情况
几个例子吧: 序列 { 1 2 3 }
共有8中情况 :
{ 1 2 3 } 对应数字(十进制)
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3
1 0 0 4
1 0 1 5
1 1 0 6
1 1 1 7
0 代表没有该数字 1代表选中该数字 当然其中有不符合条件的
对于求hash值 的公式:
p可以去大于等于max{ai}+1的任意一个值
class Solution {
public:
vector<int> temp;
vector<vector<int>> ans;
unordered_set<int> s;
int n;
// 找出 对应的数字
void findSubsequences(int mask, vector<int>& nums) {
temp.clear();
for (int i = 0; i < n; ++i) {
if (mask & 1) {
temp.push_back(nums[i]);
}
mask >>= 1;
}
}
// 判断 子序列(temp) 是不是递增子序列
bool check() {
for (int i = 1; i < temp.size(); ++i) {
if (temp[i] < temp[i - 1]) {
return false;
}
}
return temp.size() >= 2;
}
// 得到hash值
int getHash(int base, int mod) {
int hashValue = 0;
for (const auto &x: temp) {
hashValue = 1LL * hashValue * base % mod + (x + 101);
hashValue %= mod;
}
return hashValue;
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
n = nums.size();
// 共有 2的n次方 种情况 即 1<<n
// 数字 i 所对应的子序列
for (int i = 0; i < (1 << n); ++i) {
// 将找出的子序列放到 temp 中
findSubsequences(i, nums);
// 求出 hash 值
int hashValue = getHash(263, int(1E9) + 7);
// 递增 不存在
if (check() && s.find(hashValue) == s.end()) {
ans.push_back(temp);
s.insert(hashValue);
}
}
return ans;
}
};
另一个就是 递归 还是递归方便
还是枚举 每个数字有两种情况 选或者不选 当其中一种情况枚举至序列最后时 结束 (需要一个参数记录当前位置)
在选择的时候 只有当当前数值大于上一个数值时才可以选中 这满足了序列的递增 还要解决序列的不重复
对于 … a … b … (cur此时指向b a是上一个选择的元素) 对于序列 a b 共有四种情况 a选b选 a选b不选 a不选b选 a不选b不选
若 a b值相同 可以看出 a选b不选 a不选b选 是等价的 只要排除一种即可 那么 只有上一个元素不等于当前元素的时候 当前元素不选择
class Solution {
public:
vector<int> temp;
vector<vector<int>> ans;
void dfs(int cur,int last,vector<int>& nums){
int n = nums.size();
// 递归条件 枚举至端点跳出
if(n==cur){
if(temp.size()>=2){
ans.push_back(temp);
}
return;
}
// 若当前值大于前一个值
// 相当于
// temp.push_back(nums[cur]);
// dfs(cur+1,nums[cur],nums);
// temp.pop_back();
// dfs(cur+1,last,nums);
// 若当前值等于前一个值
// temp.push_back(nums[cur]);
// dfs(cur+1,nums[cur],nums);
// temp.pop_back();
// {不选择当前元素} 此种情况排除
if(nums[cur]>=last){
temp.push_back(nums[cur]);
dfs(cur+1,nums[cur],nums);
temp.pop_back();
}
if(nums[cur]!=last){
dfs(cur+1,last,nums);
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
dfs(0, INT_MIN, nums);
return ans;
}
};
先这样 最近几天有点难受 睡觉,,,