leetcode Mar 1st week

上周刷了括号匹配的问题,这周开始刷排列。

谈到排列,那算法就没得选。DFS。

比如给了一组数{1, 2, 3},让找出所有的排列。

那大家的思路一定是

1. 先把各个元素作为新的排列的第一个元素:

{1}

{2}

{3}

2. 然后每个排列中再依次把没有访问的数字插进去

{1,2}

{1, 3}

{2, 1}

{2, 3}

{3, 1}

{3, 2}

3. 重复第二步直到每个排列的长度等于3.

所以DFS来做就是基本的解法。框架如下:

DFS(result, curPerm, inputVector){

当已经排序完的组合长度和输入的数组长度一样时候

更新结果并退出递归

}

for(auto i: inputVector){

if(i 访问过)

continue;

把新的元素i放到curPerm里

递归DFS()

恢复当前for loop 刚刚开始的状态,进行下一步for loop

}}

46. Permutations 就是按照这个框架写的代码

class Solution {
public:
    void help(vector<vector<int>> &ret,vector<int> &curVec,vector<int>& nums, unordered_set<int> visited)
    {
        if(curVec.size() == nums.size()){
            ret.push_back(curVec);
            return;
        }
        
        for(int i=0;i<nums.size();i++) {
            if(visited.count(nums[i]) == 1)
                continue;
            curVec.push_back(nums[i]);
            visited.insert(nums[i]);
            help(ret, curVec, nums, visited);
            curVec.pop_back();
            visited.erase(nums[i]);
        }
        return;
    }
    
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> ret;
        vector<int> curVec;
        unordered_set<int> visited;
        
        help(ret, curVec, nums, visited);
        
        return ret;
    }
};

47. Permutations II 也是按照以上的思路去做。

但是又有一些不同,排列的结果要去重复的。

为何会有重复的那?

比如这个例子: {1, 1, 3}

我们还是按照之前的想法来做:

第一步,每个元素都作为排列组合的第一个元素:

{1}

{1}

{3}

第二步, 把剩下的没有访问的元素插入到排列组合里去。

{1, 1}

{1,   3}

{1,   1} -  array[1]=1 排在前头, array[0] = 1排在后面

{1, 3}

{3, 1}array[0]=1 插入

{3, 1}array[1] = 1插入

从第二步开始就已经有重复的了,红色的都是重复的组合。

那么如何才能去掉重复的1 那。

这个才是这道题的关键。

分析下哦。红色的这3个组合,都是有个规律哦

array[1] 先于array[0] 被访问到并放到组合里。

我们就可以用这个来去重。

当有多个重复的数字时,

必须顺序的访问这些重复的数字,比如{1,1,3}。 必须先访问第一个1, 才能访问第二个1.

如果先访问第二个1 ,就算违规。

class Solution {
public:

    
    void help(vector<vector<int>> &ret, vector<int>& curPermute, vector<int>& nums, unordered_set<int> &visitedNum)
    {
        if(curPermute.size() == nums.size()) {

                ret.push_back(curPermute);
                return;
        }
        
        for(int i =0;i<nums.size();i++) {
            if(visitedNum.count(i) ==1)
                continue;
            if(i != 0 && nums[i] == nums[i-1] &&visitedNum.count(i-1) ==0 )
                continue;

            
            curPermute.push_back(nums[i]);
            visitedNum.insert(i);
            
            help(ret, curPermute, nums, visitedNum);
            
            visitedNum.erase(i);

            curPermute.pop_back();
        }
        
        return;
    }
    
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> ret;
        vector<int> curPermute;

        unordered_set<int> visitedNum;
        sort(nums.begin(), nums.end());
        
        help(ret, curPermute, nums, visitedNum);
        
        return ret;
    }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值