LeetCode题解 Permutations II 和 Permutations I ——回溯算法

这个算法感觉还是很陌生的。算法导论里没有讲这个算法,而数据结构与算法分析只用了一节来阐述。我居然跳过去了。。尴尬。

 

笨方法解决的:

第一题:

给定一个元素不重复的数组,枚举出他们的全排列。

 

方法1:递归。

a[0] a[1] a[2]...a[n-1]这些元素的全排列,可以在 a[1]...a[n-1]的全排列的基础上,插入一个a[0]就可以获得了。

因为所有元素不重复,那么a[0]的插入位置实际上有n种。

 

方法2:回溯。实际上是深度优先搜索。

先选取一个点放入数组,再从余下的里面选取一个点,再从余下的选。。。一层层的来。

这里还有一个递归、然后回溯一步。

现在就是死记硬背的算法。实在没有深入的理解!

先记下算法:

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<int> visited(nums.size(),0);
        vector<int> last;
        
        for(int i = 0; i < nums.size(); i ++)
        {
            visited[i] = 1;
            last.push_back(nums[i]);
            back_track(nums,1,visited,last);
            last.pop_back();
            visited[i] = 0;
        }
        
        return ans;
    }

private:
    void back_track( vector<int> &a, int depth,vector<int> &visited, vector<int>&last)
    {
        if(depth == a.size())
        {
            ans.push_back(last);
            return;
        }
        for(int i = 0; i < a.size(); i++)
        {
            if(!visited[i])
            {
                visited[i] = 1;
                last.push_back(a[i]);
                back_track(a,depth + 1, visited, last);
                last.pop_back();
                visited[i] = 0;
            }
        }
    }
    vector<vector<int>> ans;
};

 

第二题:是有可能有重复的元素,这时候要求给出不重复的全排列。

思考,可能的重复是什么样的呢?

比如  1   1  1  2

按照之前的思路,选a[0]做第一个,或者a[1] a[2] a[3]

这时候,前三个当第一个,其实是一种情况。肯定会重复的。

怎样避免呢?就是保证重复元素在全排列中的顺序,和他们在数组中的顺序是一样的。

怎么实现?也就是  在这个例子中,前三个1的先后顺序必须保持一致。

保证重复的元素只有一种访问顺序,也就是靠前的先访问,靠后的后访问。

对于重复的元素:只有在前面的元素访问过以后,才可以添加后面的元素。

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<bool>visited(nums.size(),false);
        vector<int>& a = nums;
        vector<int>last;
        sort(a.begin(),a.end());
        for(int i = 0; i< nums.size(); i++)
        {
            if(i > 0 && a[i] == a[i-1] && visited[i-1] == false)
                    continue;
            
            visited[i] = true;
            last.push_back(a[i]);

            back_track(a,1,visited,last);
            
            last.pop_back();
            visited[i] = false;
        }
        
        return ans;
    }
    
    void back_track(vector<int>& a, int depth, vector<bool> &visited, vector<int>&last)
    {
        if(depth == a.size())
        {
            ans.push_back(last);
            return;
        }
        
        for(int i = 0; i < a.size(); i ++)
        {
            if(!visited[i])     //i 是未添加的
            {
                if(i > 0 && a[i] == a[i-1] && visited[i-1] == false)
                    continue;
                
                visited[i] = true;
                last.push_back(a[i]);
                back_track(a, depth + 1,visited, last );
                last.pop_back();
                visited[i] = false;
            }
        }
    }
private:
    vector<vector<int>> ans;
};

 

转载于:https://www.cnblogs.com/buddho/p/8001278.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值