java数据结构与算法之全排列问题

Posted wen-pan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java数据结构与算法之全排列问题相关的知识,希望对你有一定的参考价值。

①、问题描述

  • 给你一个字符串str,返回这个字符串的全部排列,比如:
    • str = “abc”
    • 返回,[abc , acb, bac, bca,cab,cba]
  • 注意:如果字符串str里有重复字符呢?要求返回的全排列集合里不能存在重复字符串,比如:
    • str = “aa”
    • 返回,[aa]。而不是[aa, aa]

②、解题思路

  • 这种求全排列的问题,最常见也是最容易想到的写法就是【暴力递归】
  • 注意如果str里有重复字符,那么递归时需要做【剪枝】操作来保证结果集里不会有重复字符串
  • 对于递归算法主要是【分析子问题】、【找到递归点】、【确定递归参数(需要几个参数、哪些是变参,哪些是不变参)】、【确定递归退出条件】,算法也比较简单,就直接上代码了

③、相关题目

④、代码

public class PermutationProblem 

    public static void main(String[] args) 
        List<String> list = findPermutation("aba");
        System.out.println(list);
    

    /**
     * 求string字符串的所有全排列,比如:字符串abc,他的全排列为 abc、acb、bac、bca、cab、cba
     * 比如:
     * 力扣46题:https://leetcode-cn.com/problems/permutations/submissions/
     * 力扣47题:https://leetcode-cn.com/problems/permutations-ii/
     */
    public static List<String> findPermutation(String str) 
      	// 特殊情况特殊处理
        if (str == null || str.length() < 1) 
            return null;
        
        List<String> resultList = new ArrayList<>();
        process(str.toCharArray(), 0, resultList);
        return resultList;
    

  	/**
     * @param chars   字符数组
     * @param index   当前来到的位置
     * @param resList 结果集合(将结果收集到这个list里)
     */
    public static void process(char[] chars, int index, List<String> resList) 
        // base case
        if (index == chars.length) 
            // index超过数组最后一个位置时【开始结算】(因为后面已经没有可用选择了)
            resList.add(new String(chars));
            return;
        
        // 利用缓存来剪枝(由于str只由26个小写字母组成,所以这里开一个长度为26的数组就够表示了),【这里也可以用hashSet来剪枝,原理一样】
        int[] visited = new int[26];
        // i后面的每个位置的字符,都可以来到index位置
        for (int i = index; i < chars.length; i++) 
            int position = chars[i] - 'a';
            // 【之前】有【和i位置的字符】相同的字符被交换到index位置过(那就不用交换,直接看 i + 1位置的数)
            if (visited[position] != 0) 
                continue;
            
            // 记录上,i位置的字符被交换到index位置过了
            visited[position] = 1;
            // 将i位置和index位置进行交换
            swap(chars, i, index);
            // 处理index + 1后面的位置,看看当index位置是i位置的字符时,后面的位置还有多少种可能(子问题)
            process(chars, index + 1, resList);
            // 每交换完一个位置后,进行第二轮交换时需要将上一轮交换的位置给换回来
            swap(chars, i, index);
        
    

    private static void swap(char[] chars, int i, int j) 
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;
    


以上是关于java数据结构与算法之全排列问题的主要内容,如果未能解决你的问题,请参考以下文章

回溯算法之全排列问题

STL之全排列函数poj1716

暴力之全排列

Java与算法之 - 数字全排列

Java与算法之 - 数字全排列

redis主从复制之全量复制与部分复制