剑指offer:字符串的全排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

解题思路:经典的动态规划问题,固定第一个字符,然后依次将后面的字符串与前面的交换,那么排列的个数就是除了第一个字符以外,其他字符的排列个数+1。也就是固定一个字符串之后,之后再将问题变小,只需求出后面子串的排列个数就可以得出结果,当然第一时间想到的就是递归的算法了。

递归的出口就是只剩一个字符的时候,递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串。

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class Solution {
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> list = new ArrayList<>();
        if(str.length() < 1) {
            return list;
        }
        printStr(str.toCharArray(), 0, list);
//按字典序排列
        Collections.sort(list);
        return list;
    }

    public void printStr(char[] chars, int begin, ArrayList<String> list) {
        int length = chars.length;
        if (begin == chars.length - 1) {
            list.add(String.valueOf(chars));
        } else {
            Set<Character> charSet = new HashSet<Character>();
            for (int i = begin; i < length; i++) {
                if(i != begin && charSet.contains(chars[i])) {
                    //这个判断过滤的是这种情况:acdvba,当轮到第一个a和最后一个a交换时,由于他们相等,所以交换之后并不能产生新的字符串,所以跳过这个交换。
                    continue;
                }
                charSet.add(chars[i]);
                swap(chars, begin, i);
                printStr(chars, begin + 1, list);
                swap(chars, i, begin);
            }
        }
    }

    public void swap(char[] chars, int i, int j) {
        char aChar = chars[i];
        chars[i] = chars[j];
        chars[j] = aChar;
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值