Java之字符串全排列

前言

通过对字符串的全排列,来理解回溯。

一、全排列

1、例题

输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]

2、题解

A.回溯

通过StringBuilder来回溯拼接字符,通过HashSet来去重。

class Solution {
int[] visited;
    Set<String> list = new HashSet<>();
    StringBuilder sb = new StringBuilder();

    public String[] permutation(String s) {
        int len = s.length();
        visited = new int[len];
        //每一个字符都作为起点
        for (int i = 0; i < len; i++) {
            dfs(s, i);
            visited[i] = 0;
            sb.delete(0, sb.length());
        }
        //得到set中的元素
        String[] res = new String[list.size()];
        int count = 0;
        for (String str : list) {
            res[count++] = str;
        }
        return res;
    }
	//递归组合字符
    private void dfs(String s, int i) {
        sb.append(s.charAt(i));
        visited[i] = 1;
        //递归出口,拼接完毕
        if (sb.length() == s.length()) {
            list.add(sb.toString());
            return;
        }
        //循环递归
        for (int j = 0; j < s.length(); j++) {
            if (visited[j] == 0) {
                dfs(s, j);
                visited[j] = 0;
                sb.delete(sb.length() - 1, sb.length());
            }
        }
        return;
    }

}

B.递归排列

class solutionForSearch {
    List<String> res = new LinkedList<>();
    char[] chs;

    public String[] permutation(String s) {
        chs = s.toCharArray();
        dfs(0);
        return res.toArray(new String[res.size()]);
    }

    /**
     * 私有递归去全排列
     * @param x,当前在那一层排列
     */
    private void dfs(int x) {
        if (x == chs.length - 1) {
            //如果要把数组里的元素连接成字符串,还是得String.valueOf();Arrays.toString(T[] t)是将元素按照数组的原样变成字符串。
            res.add(String.valueOf(chs));
            return;
        }
        //是否重复判断,用于后面的剪枝。
        Set<Character> set = new HashSet<>();
        for (int i = x; i < chs.length; i++) {
            //在此层,已经有该元素开头的,需剪枝。
            if (set.contains(chs[i])) continue;
            set.add(chs[i]);
            //递归前的变形
            swap(x, i);
            //开始递归
            dfs(x + 1);
            //递归完毕,恢复原样,毕竟这里时类属性,而不是局部变量。
            swap(i, x);
        }
    }

    /**
     * 私有交换方法
     * @param index1,需交换元素位置之一
     * @param index2,需交换元素位置之一
     */
    private void swap(int index1, int index2) {
        char temp = chs[index1];
        chs[index1] = chs[index2];
        chs[index2] = temp;
    }
}

总结

1)回溯、剪枝

参考文献

[1] Leetcode 原题
[2] Leetcode 解答1
[3] Leetcode 解答2

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值