算法刷题Day 29 递增子序列+全排列+全排列II

这篇具有很好参考价值的文章主要介绍了算法刷题Day 29 递增子序列+全排列+全排列II。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Day 29 回溯算法

491. 递增子序列

如果直接像下面这样写的话,会出错,出错的案例类似:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9nrEEc2S-1688623883770)(LC491-递增子序列+LC.assets/image-20230703201315163.png)]

class Solution {
    vector<vector<int>> rst;
    vector<int> path;

    void backtracking(const vector<int> &nums, int idx)
    {
        if (path.size() > 1)
        {
            rst.push_back(path);
        }

        for (int i = idx; i < nums.size(); i++)
        {
            if (i > idx && nums[i] == nums[i - 1]) // 不能使用这一去重逻辑
            {
                continue;
            }

            if (path.empty() || path.back() <= nums[i])
            {
                path.push_back(nums[i]);
                backtracking(nums, i + 1);
                path.pop_back();
            }
        }
    }

public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        rst.clear();
        path.clear();
        backtracking(nums, 0);
        return rst;
    }
};

本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。

所以不能使用之前的去重逻辑!

同一父节点下的同层上使用过的元素就不能再使用了

正确的写法如下:

class Solution {
    vector<vector<int>> rst;
    vector<int> path;

    void backtracking(const vector<int> &nums, int idx)
    {
        if (path.size() > 1)
        {
            rst.push_back(path);
        }

        int used[201] = {0};

        for (int i = idx; i < nums.size(); i++)
        {
            if ((!path.empty() && path.back() > nums[i]) || used[nums[i] + 100])
            {
                continue;
            }
            used[nums[i] + 100] = 1;
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }

public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        rst.clear();
        path.clear();
        backtracking(nums, 0);
        return rst;
    }
};

46. 全排列

需要有一个used数组来记录已经被使用过的元素索引

class Solution {
    vector<vector<int>> rst;
    vector<int> path;

    void backtracking(const vector<int> &nums, vector<bool> &used) 
    {
        if (path.size() == nums.size())
        {
            rst.push_back(path);
            return;
        }

        for (int i = 0; i < nums.size(); ++i)
        {
            if (used[i]) continue;
            used[i] = true;
            path.push_back(nums[i]);
            backtracking(nums, used);
            path.pop_back();
            used[i] = false;
        }
    }

public:
    vector<vector<int>> permute(vector<int>& nums) {
        rst.clear();
        path.clear();
        vector<bool> used(nums.size(), false);
        backtracking(nums, used);
        return rst;
    }
};

47. 全排列II

还要强调的是去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了文章来源地址https://www.toymoban.com/news/detail-612872.html

class Solution {
    vector<vector<int>> rst;
    vector<int> path;

    void backtracking(const vector<int> &nums, vector<bool> &used)
    {
        if (path.size() == nums.size())
        {
            rst.push_back(path);
            return;
        }

        for (int i = 0; i < nums.size(); ++i)
        {
            if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])
            {
                continue;
            }

            if (!used[i])
            {
                used[i] = true;
                path.push_back(nums[i]);
                backtracking(nums, used);
                path.pop_back();
                used[i] = false;
            }
        }
    }

public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        rst.clear();
        path.clear();
        sort(nums.begin(), nums.end());
        vector<bool> used(nums.size(), false);
        backtracking(nums, used);
        return rst;
    }
};

到了这里,关于算法刷题Day 29 递增子序列+全排列+全排列II的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [100天算法】-全排列 II(day 51)

    时间复杂度: 空间复杂度: JavaScript Code

    2024年02月06日
    浏览(31)
  • java数据结构与算法刷题-----LeetCode667. 优美的排列 II

    java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完): https://blog.csdn.net/grd_java/article/details/123063846 解题思路 题目要求我们返回一个数组长度为n的数组,必须含有1~n的所有数,并且从左到右,相邻的元素依次相减,它们的差,必

    2024年01月25日
    浏览(41)
  • 算法刷题Day 37 单调递增的数字+监听二叉树

    两个可能经常要用到的函数 字符串转数字: to_string() 数字转字符串: stoi() 利用树后续遍历,同时加上状态转移的方法,非常值得反复学习

    2024年02月13日
    浏览(26)
  • [100天算法】-最长递增子序列的个数(day 47)

    思路 代码 JavaScript Code C++ Code 复杂度分析 时间复杂度:$O(N^2)$。N 是数组  nums  的长度。 空间复杂度:$O(N)$。N 是辅助数组  length  和  count  的长度。

    2024年02月07日
    浏览(36)
  • 算法刷题Day 39 不同路径+不同路径II

    递归(深搜) 使用递归的方法超时(可以过37个case) 来分析一下时间复杂度,这个深搜的算法,其实就是要遍历整个二叉树。 这棵树的深度其实就是m+n-1(深度按从1开始计算)。 那二叉树的节点个数就是 2^(m + n - 1) - 1。可以理解深搜的算法就是遍历了整个满二叉树(其实没

    2024年02月12日
    浏览(34)
  • 算法刷题Day 28 复原IP地址+子集+子集II

    我的做法有点奇怪,还是参考一下代码随想录的做法吧 涉及到去重,可别忘了排序 不然去重的效果没法实现

    2024年02月16日
    浏览(32)
  • 算法刷题Day 59 下一个更大元素II+接雨水

    其实也可以不扩充nums,而是在遍历的过程中模拟走了两边nums 三种方法都写了一遍 暴力方法 逐列计算 找到当前位置,左边最高的柱子的索引和右边最高的柱子的索引,两者中相对小的那个,将去当前位置的高度,就是水柱的高度,而宽度是1 超时了 双指针 提前记录好左边最

    2024年02月14日
    浏览(30)
  • 力扣算法刷题Day39|动态规划:不同路径 I&II

    力扣题目:#62.不同路径 刷题时长:参考题解后10min 解题方法:动规 复杂度分析 时间O(m*n) 空间O(m*n) 问题总结 初始化二维数组的python语法:i 对应 m,j 对应n 二维遍历顺序,从上到下从左到右通过两层for循环实现,其中startindex应为1 本题收获 动规思路 确定dp数组及下标的含义

    2024年02月12日
    浏览(46)
  • 算法刷题Day 27 组合总和+组合总和II+分割回文子串

    本题的特点是元素为可重复选取的 其实只要在原来的基础上添加一点小小的变化就是实现重复选取(与排列区别开),一时没想出来 这里与39.组合总和 (opens new window)最大的不同就是要去重了。 前面我们提到:要去重的是“同一树层上的使用过”,如何判断同一树层上元素(

    2024年02月14日
    浏览(28)
  • 算法刷题Day 31 分发饼干+摆动序列+最大子序列和

    分发饼干其实有很多种写法,但是下面这种贪心的解法是最好理解,也最好解释的 我的其他解法 贪心算法 这道题用贪心算法要考虑的细节有很多。 动态规划 有点难(甚至涉及到了线段树),等后面二刷的时候再来学好了 暴力解法 超时了 贪心算法 贪心算法的代码写起来简

    2024年02月15日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包