面试题 08.08. 有重复字符串的排列组合-20230227

1、题目:面试题 08.08. 有重复字符串的排列组合

2、思路

  • 利用set集合

        前面逻辑同面试题 08.07. 无重复字符串的排列组合,利用set集合的不可重复性,将所有排列组合都放入set集合中,set集合会将重复的去掉,但是会遍历所有的排列组合,时间复杂度高。

  • 剪枝

        当该位置上面的字符在之前已经填入过相同的字符时,就不需要再填入这个字符,就将这个字符的分支去掉。

3、代码

  • 利用set集合

class Solution {
    // set集合去重
    private Set<String> res = new HashSet<>();

    public String[] permutation(String S) {
        char[] cs = S.toCharArray();
        dfs(cs, 0);

        return res.toArray(new String[0]);
    }

    private void dfs(char[] cs, int index) {
        if (index == cs.length - 1) {
            res.add(new String(cs));
            return;
        }

        for (int i = index; i < cs.length; i++) {
            swap(cs, index, i);
            dfs(cs, index + 1);
            swap(cs, index, i);
        }
    }

    /**
     * 交换数组中的两个元素
     */
    private void swap(char[] cs, int i, int j) {
        char temp = cs[i];
        cs[i] = cs[j];
        cs[j] = temp;
    }
}
  • 剪枝(进阶)

class Solution {
    private List<String> res = new ArrayList<>();

    private Set[] set;

    public String[] permutation(String S) {
        char[] cs = S.toCharArray();
        this.set = new Set[cs.length];
        for (int i = 0; i < set.length; i++) {
            set[i] = new HashSet();
        }
        dfs(cs, 0);

        return res.toArray(new String[0]);
    }

    private void dfs(char[] cs, int index) {
        if (index == cs.length - 1) {
            res.add(new String(cs));
            return;
        }

        for (int i = index; i < cs.length; i++) {
            // 判断该位置是否已经使用过cs[i]字符了
            if (!set[index].contains(cs[i])) {
                swap(cs, index, i);
                // 表示该字符已经出现在该位置上了, 下次遍历到相同字符直接跳过
                set[index].add(cs[index]);
                dfs(cs, index + 1);
                swap(cs, index, i);
            }
        }
        // 该位置已经遍历所有字符, 将标识数组回溯到初始状态
        set[index].clear();
    }

    /**
     * 交换数组中的两个元素
     */
    private void swap(char[] cs, int i, int j) {
        char temp = cs[i];
        cs[i] = cs[j];
        cs[j] = temp;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值