《剑指offer》面试题28:字符串的排列(java实现)

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

——来源于《剑指offer》

感谢这篇文章的作者:字符串全排列算法学习

  • 解题思路:

    • 我们可以先考虑特例,即字符串中没有重复字符的时候该怎么办。
    • 没有重复字符的时候我们可以,固定第一位,使第一位依次与后面的各位交换。然后递归对第一位后面的子字符串进行相同操作。
    • 然后我们考虑有重复项的时候:例如:对abb,第一个数a与第二个数b交换得到bab,然后考虑第一个数与第三个数交换,此时由于第三个数等于第二个数,所以第一个数就不再用与第三个数交换了。再考虑bab,它的第二个数与第三个数交换可以解决bba。此时全排列生成完毕!
  • 代码实现:

import java.util.*;

/**
 * @author lijing
 * @date 2019-08-03 16:22
 * @description 字符串全排列
 */
public class Solution {

    private ArrayList<String> list = new ArrayList<>();

    public ArrayList<String> Permutation(String str) {
        if (str == null || str.equals("")) {
            return list;
        }
        Permutation(str.toCharArray(), 0);
        Collections.sort(list);
        return list;
    }

    private void Permutation(char[] array, int index) {
        if (index == array.length - 1) {
            list.add(String.valueOf(array));
        } else {
        // 将交换过的字符存入set中,如果set中有上次已经交换过的字符,就不再进行交换
            HashSet<Character> set = new HashSet<>();
            for (int i = index; i < array.length; i++) {
                if (i == index || !set.contains(array[i])) {
                    set.add(array[i]);
                    swap(array, i, index);
                    Permutation(array, index + 1);
                    // 这一步是将交换过的序列再交换回去,再进行下一次循环
                    swap(array, i, index);
                }
            }
        }
    }

    private void swap(char[] array, int i, int j) {
        char temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public static void main(String[] args) {
        System.out.println(new Solution().Permutation("abb"));
    }
}

你可能感兴趣的:(面试题)