剑指Offer面试题:字符串的排列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/H_Targaryen/article/details/82291728

字符串的排列

题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

分析

  • 只需要得到所有的字符串,然后对集合进行排序即可
  • 对于这种问题,可以先从abc的例子入手,从特殊解到一般解
    • 第一步:没有固定的字符,将a和a、b、c分别交换得到abc、bac、cba
    • 第二步:对于每一种情况,将第一个字符固定,对剩下的部分进行交换(比如对于abc,将a固定,将b和b、c进行交换得到abc、acb)
  • 将问题拆分为小的部分,很明显是一种递归,递归结束的条件是遍历到了字符串的末尾
  • 边界条件
    • 空字符串
import java.util.ArrayList;
import java.util.Collections;

public class Solution {
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> result = new ArrayList<String>();
        if(str == null) //边界条件
            return result;

        char[] cs = str.toCharArray();
        PermutationHelper(cs,0,result);
        Collections.sort(result);
        return result;
    }
    public void PermutationHelper(char[] cs, int i, ArrayList<String> result){ //字符集合,固定元素位置,结果集
        if(i == cs.length-1){
            if(!result.contains(new String(cs))){
                result.add(new String(cs)); //String()构造方法传参为char[]数组,生成字符串
                return; //返回到上一层
            }
        } else{
            for(int j=i; j < cs.length; j++){
                Swap(cs,i,j);
                PermutationHelper(cs,i+1,result); //这里为什么i成为了i+1?表示当前层的交换进行成功,第i个元素已经固定
                Swap(cs,i,j); //复原数组到上一步
            }
        }
    }

    public void Swap(char[] cs, int i, int j){
        char tmp = cs[i];
        cs[i] = cs[j];
        cs[j] = tmp;
    }
}
  • 这道题理解了很久,很有回溯法的精髓
  • 首先是变量的含义
    • i表示从下标0开始到i(不包含i)的字符是已经固定的
    • j用于从i到数组末尾的字符的交换
    • 因为数组只有一个,每次从栈中退回需要还原之前的状态
    • 对于最后的结果,使用Collections.sort()方法进行字典序排序

猜你喜欢

转载自blog.csdn.net/H_Targaryen/article/details/82291728