leetcode_46. Permutations


常规DFS思路:
void P(vector<vector<int>> &result,vector<int> &nums,vector<int> &now,vector<bool> &flag,int index)
    {
        if(index==nums.size())
            result.push_back(now);
        else
        {
            for(int i=0;i<nums.size();i++)
            {
                if(flag[i]==false)
                {
                    now.push_back(nums[i]);
                    flag[i]=true;//用来记录是否被使用过
                    P(result,nums,now,flag,index+1);
                    now.pop_back();
                    flag[i]=false;
                }
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        vector<bool> flag(nums.size(),false);//vector初始化
        vector<int> now;
        vector<vector<int>> result;
        P(result,nums,now,flag,0);
        return result;
    }

除此之外,看到一种基于交换的方法,看着更加简洁,但是略微影响了输出的顺序(不是按字典序输出了)
 
void permuteRecursive(vector<int> &num, int begin, vector<vector<int> > &result) { if (begin==num.size()-1) {//此处不用到num.size(),因为最后一次必然是自我交换,可以提前结束 result.push_back(num);
                    return;
                } for (int i = begin; i < num.size(); i++) { swap(num[begin], num[i]); permuteRecursive(num, begin + 1, result); swap(num[begin], num[i]);//回溯,但若传入的是num,不是&num,则无需回溯,因为是局部变量,但效率会更低 } } vector<vector<int> > permute(vector<int> &num) { vector<vector<int> > result; permuteRecursive(num, 0, result); return result; }

下面是存在重复数字的解法:
void recursion(vector<int> num, int i, int j, vector<vector<int> > &res) { if (i == j-1) { res.push_back(num); return; } for (int k = i; k < j; k++) { if (i != k && num[i] == num[k]) continue;//多了一行重复判断 swap(num[i], num[k]); recursion(num, i+1, j, res);//此处不能回溯
} } vector<vector<int> > permuteUnique(vector<int> &num) { sort(num.begin(), num.end()); vector<vector<int> >res; recursion(num, 0, num.size(), res); return res; }

本以为传入&num并回溯和传入num不回溯是没有区别的,但是此处回溯就回出错,两者其实是有略微区别的,若回溯,那么数组在第二个swap语句结束时,直接还原,若不回溯,则数组会在整个for循环结束后再还原。此处很抽象,也难以理解如何保证不重复的,下面有回溯的解法:
void permuteRecursive(vector<int> &num, int begin, vector<vector<int> > &result) {
  if (begin >= num.size()) {
      result.push_back(num);
      return;
  }
  for (int i = begin; i < num.size(); i++) {
            int flag=false;
            for(int j=begin;j<i;j++) //特意为了排除1122中二号位与4号位交换成1221这种情况,这种相同数字的相对位置发生改变的情况必然会导致接下来的重复
                if(num[j]==num[i])
                {flag=true;break;}
            if(i==begin||flag==false)
            {
             swap(num[begin], num[i]);
             permuteRecursive(num, begin + 1, result);
             swap(num[begin], num[i]);
            }
    }
    }
        vector<vector<int>> permuteUnique(vector<int> &num) {
     vector<vector<int> > result;
        sort(num.begin(),num.end());
     permuteRecursive(num, 0, result);
     return result;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值