美文网首页
一维数组上的DFS(一):排列问题

一维数组上的DFS(一):排列问题

作者: 进击的Lancelot | 来源:发表于2020-06-14 12:15 被阅读0次

基本问题描述

给定一个可包含重复数字的序列,返回所有不重复的全排列。

Example

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

题目链接:47. 全排列 II (难度:中等)

模板(枚举全排列)

vector<int> res(len, 0);  // 存放临时结果
vector<vector<int>> ans;
bool visited[16];  //标记已访问过的元素
void dfs(vector<int>& nums, int idx, int len){
    if(idx == len){
        ans.push_back(res);
        return;
    }
    for(int i = 0;i < len;++i){
        if(visited[i])  continue;
        // 对于最基础的全排列问题,相当于构造性和剪枝性约束条件都为永真条件
        //对于不满足构造性条件的元素,不添加入 res 当中
        if(构造性约束条件1){
            res[idx] = nums[i];
            visited[i] = true;
            // 若满足剪枝性约束,则直接回溯,不再继续递归下去
            if( ! 剪枝性约束条件){
                dfs(nums, idx + 1, len);
            }
            visited[i] = false;
        }
    }
}

思路

对于在一维数组上的 DFS 问题, 我将其分为 4 类问题,分别是排列问题, 组合问题, 子串分割问题以及其他. 对于很多一维数组上的 DFS 问题, 往往可以转化为一个基础问题 + 约束条件 st.
回到 全排列II 问题本身,我们已知基础问题是枚举全排列,而约束条件st 则是去除重复的排列. 为了达到去除重复排列的目的,我们可以先对原有序列进行排序,使相同的元素靠在一起. 当回溯时,如果某元素 x 在上次枚举排列时已经被使用过,则在此次的枚举过程当中应当跳过.

代码

class Solution {
public:
    bool visited[16] = {false};
    void dfs(int idx,int n,vector<int>& nums, vector<int>& res, vector<vector<int>>& ans){
        if(idx == n){
            ans.push_back(res);
            return;
        }
        int sample = INT_MIN;
        for(int i = 0;i < n;++i){
            if(visited[i] || sample == nums[i])  continue;
            visited[i] = true;
            res[idx] = nums[i];
            sample = nums[i];
            dfs(idx+1,n,nums,res,ans);
            visited[i] = false;
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        if(nums.empty()) return {};
        int n = nums.size();
        vector<int> res(n, 0);
        vector<vector<int>> ans;
        sort(nums.begin(),nums.end());
        dfs(0,n,nums,res,ans);
        return ans;
    }
};

执行结果: 8 ms, 7.6 MB

相关的练习题:

使用基本问题模板 + 约束条件的方法,可以将相当一部分的问题整合成一类问题,把注意力集中到如何用代码表述约束条件以及将条件放入到模板的哪个位置即可,而无需每次都针对问题去思考新的做法.

  1. 问题:Leetcode 89. 格雷编码(中等)【st:相邻元素的二进制表示仅有1位不同 基础问题:枚举数组[0,1,2,...]全排列并找到一个符合条件的全排列 剪枝技巧:直接生成仅有1位不同的数字】
    题解:Leetcode 89. 格雷编码(回溯算法)
  2. 问题:1079. 活字印刷(中等) 【st:生成长度分别为1,2, .. , n 的不重复的排列 基础问题:枚举给定数组的所有长度的排列】
    题解:Leetcode 1079. 活字印刷(回溯算法 + 带重复元素的全排列)
  3. 问题:526. 优美的排列 (中等)【st:第 i 位的数字能被 i 整除 或 i 能被第 i 位上的数字整除; 基础问题:枚举全排列】
    题解: Leetcode 526. 优美的排列(回溯算法)
  4. 问题: 996. 正方形数组的数目 (困难)【st:相邻元素和为完全平方数 基础问题:枚举数组的全排列】
    题解:Leetcode 996. 正方形数组的数目(回溯算法+全排列问题)

相关文章

  • 一维数组上的DFS(一):排列问题

    基本问题描述 给定一个可包含重复数字的序列,返回所有不重复的全排列。 Example 输入: [1,1,2]输出:...

  • 46. Permutations

    Description 找到数组全排列 Solution 暴力dfs with sortTime O(N! *N ...

  • [DFS]求全排列问题

    问题:全排列的种树是N!,要求按字典序输出。思路:我们可以把N个数两两建立无向边(即任意两个结点之间都有边,也就是...

  • leetcode指北---DFS

    DFS,也就是深搜,实质就是枚举。如果题目问的是一共多少种方法,多少种排列...尽管用。 全排列问题: 全排列:给...

  • Combination Sum

    标签: C++ 算法 LeetCode 数组 DFS 每日算法——leetcode系列 问题 Combinat...

  • 数组全排列问题

    最近看到剑指offer上一道数组全排列的题目,看似很简单,仔细分析一下,还是有点难以理解,特此在这拆解下,希望能够...

  • Leetcode上的dfs问题

    下面的题目是我刷的Leetcode上关于深度优先搜索的题目,因为题还没刷完,所以这篇文章会将不时地进行续更

  • 旅行商问题

    旅行商问题是一个NP问题。最简单的解法是枚举法:全排列,DFS 根据http://blog.csdn.net/q_...

  • 岛屿问题

    岛屿系列题目的核心考点就是用 DFS/BFS 算法遍历二维数组。本文分析DFS算法。 一、框架 因为二维矩阵本质上...

  • LeetCode 977. Squares of a Sorte

    问题描述 给定一个升序排列的整形数组,要求返回每个元素计算平方值之后的数组,且升序排列。 栗子 1: 栗子 2: ...

网友评论

      本文标题:一维数组上的DFS(一):排列问题

      本文链接:https://www.haomeiwen.com/subject/gflxxktx.html