详细解析字符串的排列(剑指offer java版)

字符串的排列

题目描述

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

思路

递归:(基于回溯法)即先固定第一个字符,递归取得首位后面的各种字符串组合;再把第一个字符与后面每一个字符交换,再次递归获得首位后面的字符串组合。 若是过程中遇到重复值,比如当前首位字母为A,下一位字母也为A,则不交换.(即使交换了也一样。) 那么如何判断之前的字符串中有没有存在当前字母呢? 可以选择使用HashSet,来自动判断当前的Set中有没有重复。 经典图示: 避坑提示: 1.在每个分支进行完后,一定要将交换过的元素复位,避免影响其他分支。 2.因为有“Swap A with A”这样的操作,并且题目指出可能有字符重复,所以分支末尾可能有重复的序列,在加入ArrayList要进行去重判断,不重复再加入。

/**
本题把字符串分为两部分:part1是字符串的被固定的最后一个字符,part2是被固定的最后一个字符以后的所有字符。
第一步是(for循环、交换操作)
目的是求所有可能出现在第一个位置的字符,即把第一个字符和后面所有字符交换。
第二步是采用递归
固定住第一个字符,求后面所有字符的排列。
而“求后面所有字符的排列”这一步就可以按照上面的思路递归进行。
需要字符串转换为字符数组,使用toCharArray()方法
**/
import java.util.ArrayList;
import java.util.Collections;
public class Solution {
          
   
    public ArrayList<String> Permutation(String str) {
          
   
        ArrayList<String> res = new ArrayList<>();
        if(str == null || str.length() == 0){
          
   
            return res;
        }
         permu(str.toCharArray(),0,res);
         Collections.sort(res);
         return res;
    }
    public void permu(char[] chars,int index,ArrayList<String> list){
          
         
        if(index == chars.length-1){
          
   //去重,当递归交换到最后一个位置的时候,就看看list有么有这个字符串,没有的话就放进去。
            String val = String.valueOf(chars);
            if(!list.contains(val)){
          
   
                list.add(val);
            }
        }else{
          
   //循环来执行交换操作,先交换,然后固定这个,下一个交换。
          for(int i = index;i < chars.length;i++){
          
   //注意这里一定是index,而不是index+1,否则会有遗漏元素
              swap(chars,index,i);
              permu(chars,index+1,list);//依次固定一个,注意固定的是index
              swap(chars,index,i);//最后一定要交换回来不要影响之后的执行
           }
        }       
        //return list;
    }    
    public void swap(char[] chars,int i ,int j){
          
   
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;       
    }
}
经验分享 程序员 微信小程序 职场和发展