面试题 08.07. 无重复字符串的排列组合-20230226

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

无重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合,字符串每个字符均不相同。

示例1:

输入:S = "qwe"

输出:["qwe", "qew", "wqe", "weq", "ewq", "eqw"]

示例2:

输入:S = "ab"

输出:["ab", "ba"] 

2、思路

 这是一道经典的回溯算法题,我们可以遍历排列的每个位置,每个位置就将字符填进去一遍,同时用一个数组标识字符串中每个位置的字符是否被用过,如果被用过了,这个字符就不能再填入这个位置。

3、代码

  • 操作字符串(效率低)

class Solution {
    private List<String> res;

    private String S;

    private boolean[] flag;

    public String[] permutation(String S) {
        this.S = S;
        this.res = new ArrayList<>();
        this.flag = new boolean[S.length()];

        dfs("");

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

    private void dfs(String s) {
        if (s.length() == S.length()) {
            res.add(s);
            return;
        }

        for (int i = 0; i < S.length(); i++) {
            if (!flag[i]) {
                flag[i] = true;
                dfs(s + S.charAt(i));
                flag[i] = false;
            }
        }
    }
}

提交记录:

  • 操作字符数组(优化,效率高)

        我们将字符串转换成字符数组,字符串底层也是字符数组,但是每一个新的字符串都会创建新的字符数组,所以不仅浪费空间,也浪费时间;而转换成字符数组之后,我们就只需要对这个数组进行操作,不用扩容之类的,就能很节约资源和性能。

        我们遍历整个数组,将当前下标的字符和之后下标的字符两两交换,每次当前下标之前的位置都是排好的,不会担心之后的字符会出现用过的,所以进一步优化代码,省略掉标识数组。

class Solution {
    private List<String> res = new ArrayList<>();
    
    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;
    }
}

提交记录:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值