LeetCode刷题笔记 字节每日打卡 字符串的排列

输入一个字符串,打印出该字符串中字符的所有排列。

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:

输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

 参考:力扣


 vis存储当前字符是否加入了数组

先排序-主要是为了处理相同字符

回溯法:

  •  如果长度满足要求,加入即可
  • 遍历每个字符
    • 如果vis true则说明已经加入了 跳过
    • 如果和前一个重复并且前一个未加入(确保加入次序为从左到右,即一次)跳过
    • 加入字符 进入下一回溯 删除字符

 把结果处理输出

注意:重点在于重复字符处理部分

class Solution {
    // 结果
    List<String> rec;
    boolean[] vis;

    public String[] permutation(String s) {
        // s的长度
        int n = s.length();
        // 储存结果
        rec = new ArrayList<String>();
        // 如果该位置已被填过即为true
        vis = new boolean[n];
        char[] arr = s.toCharArray();
        // 先排序,主要是防止相同字符
        Arrays.sort(arr);
        // 临时变量存储
        StringBuffer perm = new StringBuffer();
        // 回溯法
        backtrack(arr, 0, n, perm);
        int size = rec.size();
        String[] recArr = new String[size];
        for (int i = 0; i < size; i++) {
            recArr[i] = rec.get(i);
        }
        return recArr;
    }
    // i-遍历到第几个字符
    public void backtrack(char[] arr, int i, int n, StringBuffer perm) {
        if (i == n) {
            // 长度符合要求,加入一个到结果
            rec.add(perm.toString());
            return;
        }
        for (int j = 0; j < n; j++) {
            // 如果已经加入 或者 当前不是重复字符串第一个未填入的 (和前一个重复,但是前一个未填入)
            if (vis[j] || (j > 0 && !vis[j - 1] && arr[j - 1] == arr[j])) {
                continue;
            }
            // 加入字符
            vis[j] = true;
            perm.append(arr[j]);

            backtrack(arr, i + 1, n, perm);
            // 回溯
            perm.deleteCharAt(perm.length() - 1);
            vis[j] = false;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值