首页 > 编程语言 >代码随想录算法训练营day29 | leetcode 491. 非递减子序列、46. 全排列、47. 全排列 II

代码随想录算法训练营day29 | leetcode 491. 非递减子序列、46. 全排列、47. 全排列 II

时间:2024-03-21 14:45:28浏览次数:22  
标签:排列 day29 nums 随想录 back vector path backtracking size

目录

题目链接:491. 非递减子序列-中等

题目描述:

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

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

示例 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]]

提示:

  • 1 <= nums.length <= 15
  • -100 <= nums[i] <= 100

注意去重

代码如下:

// 时间复杂度: O(n * 2^n)
// 空间复杂度: O(n)
class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void backtracking(vector<int>& nums, int startIndex) {
        if (path.size() >= 2) {
            res.push_back(path);
        }
        // return可省略
        if (startIndex >= nums.size())
            return;
        unordered_set<int> uset;
        for (int i = startIndex; i < nums.size(); ++i) {
            if (!path.empty() && nums[i] < path.back())
                continue; // 这里用continue而不是break,因为题目说的子序列并不是连在一起的
            if (uset.find(nums[i]) != uset.end())
                continue;
            /*
            // 这里不能这么写,因为nums不是排序过的数组
            // if(i > startIndex && nums[i] == nums[i - 1])
            //     continue;
            */
            uset.insert(nums[i]);
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        backtracking(nums, 0);
        return res;
    }
};

题目链接:46. 全排列-中等

题目描述:

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

排列问题,startIndex0开始,因此可以不用

代码如下:

// 时间复杂度: O(n!)
// 空间复杂度: O(n)
class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    unordered_set<int> uset;
    void backtracking(vector<int>& nums) {
        if (path.size() == nums.size()) {
            res.push_back(path);
            return;
        }
        for (int i = 0; i < nums.size(); ++i) {
            if(uset.find(nums[i]) != uset.end())
                continue;
            uset.insert(nums[i]);
            path.push_back(nums[i]);
            backtracking(nums);
            path.pop_back();
            uset.erase(nums[i]);
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        backtracking(nums);
        return res;
    }
};

题目链接:47. 全排列 II-中等

题目描述:

给定一个可包含重复数字的序列 nums按任意顺序 返回所有不重复的全排列。

示例 1:

输入:nums = [1,1,2]
输出:
[[1,1,2],
 [1,2,1],
 [2,1,1]]

示例 2:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

提示:

  • 1 <= nums.length <= 8
  • -10 <= nums[i] <= 10

这里的去重跟其他去重不太一样,是两层去重逻辑的结合

代码如下:

// 时间复杂度: O(n! * n)
// 空间复杂度: O(n)
class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void backtracking(vector<int>& nums, vector<bool>& used) {
        if (path.size() == nums.size()) {
            res.push_back(path);
            return;
        }
        for (int i = 0; i < nums.size(); ++i) {
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false)
                continue;
            if (used[i] == false) {
                used[i] = true;
                path.push_back(nums[i]);
                backtracking(nums, used);
                path.pop_back();
                used[i] = false;
            }
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<bool> used(nums.size(), false);
        sort(nums.begin(), nums.end());
        backtracking(nums, used);
        return res;
    }
};

标签:排列,day29,nums,随想录,back,vector,path,backtracking,size
From: https://www.cnblogs.com/lurk3r/p/18087346

相关文章

  • 代码随想录第15天|二叉树的层序遍历
    二叉树的层序遍历102.二叉树的层序遍历-力扣(LeetCode)代码随想录(programmercarl.com)讲透二叉树的层序遍历|广度优先搜索|LeetCode:102.二叉树的层序遍历_哔哩哔哩_bilibili给你二叉树的根节点 root ,返回其节点值的 层序遍历 。(即逐层地,从左到右访问所有节点)......
  • 代码随想录第14天|二叉树的递归遍历
    二叉树的理论基础代码随想录(programmercarl.com)关于二叉树,你该了解这些!|二叉树理论基础一网打尽,二叉树的种类、二叉树的存储方式、二叉树节点定义、二叉树的遍历顺序_哔哩哔哩_bilibili二叉搜索树:二叉搜索树是一个有序树。左子树不为空,则左子树上所有节点的值均小于根......
  • 01天【代码随想录算法训练营34期】 第一章 数组part01 (704. 二分查找、 27. 移除元
    二分查找classSolution(object):defsearch(self,nums,target):low=0high=len(nums)-1while(low<=high):mid=(high+low)//2ifnums[mid]==target:returnmide......
  • 【代码随想录】广度优先搜索
    思路分析先前已经做过一道深度优先搜索了,可以看出,DFS比较适合求两点之间的所有路径这样的问题,因为其路径都是逐条求出的,而BFS则可能一下子求出多条路径,适合用来求最短路径。关于BFS的过程前面已经学习过很多次了,遍历到一个节点时要先保存其所有邻接节点再继续向下遍历,一般是使......
  • 代码随想录刷题记录第一天 | 数组 | 704. 二分查找,27. 移除元素
    题目链接:704.二分查找-https://leetcode.cn/problems/binary-search/description/27.移除元素-https://leetcode.cn/problems/remove-element/description/文章学习链接:https://programmercarl.com/数组理论基础.html视频学习链接:https://www.bilibili.com/video/BV1f......
  • 代码随想录算法训练营第十三天|239. 滑动窗口最大值、347.前 K 个高频元素、总结
    题目:239.滑动窗口最大值文章链接:代码随想录视频链接:LeetCode:239.滑动窗口最大值题目链接:力扣题目链接图释:classSolution{public://自己定义一个优先队列classMyQueue{public: deque<int>deq; //弹出 voidpop(intvalue){ //当输入的数组与队顶......
  • 代码随想录算法训练营第十一天| 20. 有效的括号、1047. 删除字符串中的所有相邻重复项
    题目:20.有效的括号文章链接:代码随想录视频链接:LeetCode:20.有效的括号题目链接:力扣题目链接图释:classSolution{public://有效的括号boolisValid(strings){ //遇到左括号时就放入右括号,遇到右括号时,与栈内的顶元素进行比较 //情况一:与栈顶元素相等,则是t......
  • 代码随想录算法训练营第五十二天 | 718. 最长重复子数组 ,674. 最长连续递增序列,300.最
    300.最长递增子序列 已解答中等 相关标签相关企业 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] ......
  • 代码随想录 第二十四天| ●回溯 理论基础 ● 77. 组合
    回溯理论基础:回溯三部曲:制定回溯函数的参数和返回值确定回溯终止条件确定回溯遍历过程 回溯模板voidbacktracking(参数){if(终止条件){存放结果;return;}for(选择:本层集合中元素(树中节点孩......
  • 【代码随想录】深度优先搜索
    首先了解一下深度优先搜索和回溯法的区别可以看出这两种方法在思路上可以说没什么区别,但是由于在具体实现方面的区别,有着不同的应用场景。我的理解是,回溯法很多时候是应用在抽象的枚举过程中的,而dfs算法很多时候是用在图或者树这种实际的几何图形中的。比较一下回溯的模版和df......