力扣含有重复元素的全排列

以下两题剪枝的条件都是,如果当前元素为1或者当前元素等于前面的元素,那么前面那个元素还没有出现过,则当前这个元素也不能出现。
在这里插入图片描述

//C++
class Solution {
public:
    vector<vector<int>>ans;//回溯+去重
    vector<int>temp;
    int hash[10];

    void dfs(vector<int>nums,int dep){

        if(dep == nums.size()){
            ans.push_back(temp);
            return;
        }
        for(int i=0;i<nums.size();i++){
            /*
     hash[i]:当前数字是否出现过
    * 如果当前数字与前一个数字相同(nums[i] == nums[i - 1]),
    * 并且前一个数字还没有出现的话(vis[i - 1] == false),
    * 那么就不能选择当前数字(continue),
    * 如果前面的数字已经出现过(vis[i] == true),则可以,总之相邻重复出现的元素,只能够前一个元素出现,后一个元素才能出现,这样就保证了唯一性。
    * 选择当前数字
    */
            if(hash[i] || (i > 0 && nums[i] == nums[i - 1] && !hash[i - 1]))continue;
            hash[i]=1;
            temp.push_back(nums[i]);
            dfs(nums,dep+1);
            temp.pop_back();
            hash[i]=0;
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        memset(hash,0,sizeof(hash));
        sort(nums.begin(),nums.end());
        dfs(nums,0);

        return ans;
    }
};

在这里插入图片描述

//JAVA
class Solution {
List<String>ans = new ArrayList<>();
    StringBuilder temp = new StringBuilder();
    public void dfs(char[] arr,int n,int[] visted){
        if(temp.length() == n){
            ans.add(temp.toString());
        }

        for(int i=0;i<n;i++){
            if(visted[i] == 1||(i>0&&arr[i] == arr[i-1]&&visted[i-1]==0))continue;//对于相邻且相同的元素,只有当前一个元素出现后,这个元素可以出现。

            visted[i]=1;
            temp.append(arr[i]);
            dfs(arr,n,visted);
            visted[i]=0;
            temp.deleteCharAt(temp.length()-1);
        }
    }

    public String[] permutation(String S) {
        char[] arr = S.toCharArray();
        Arrays.sort(arr);
        int n = S.length();
        int[] visted = new int[n];
        dfs(arr,n,visted);
        return ans.toArray(new String[ans.size()]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值