zoukankan      html  css  js  c++  java
  • 剑指Offer_#38_字符串的排列

    剑指Offer_#38_字符串的排列

    Contents

    题目

    输入一个字符串,打印出该字符串中字符的所有排列。
    你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
    示例:

    输入:s = "abc"
    输出:["abc","acb","bac","bca","cab","cba"]

    限制:

    1 <= s 的长度 <= 8

    思路分析

    全排列

    根据高中数学学过的排列组合相关知识,n个元素的所有排列数是
    推导思路很简单,就是一位一位地去固定元素,第1个位置有种可能,第2个位置有种可能,...最后1位有一种可能。把这些乘起来就得到
    这个思路可以直接应用到这题上面,下图很好的展示了这个思路。

    得到所有排列的过程

    • 先固定第1位,有3个选择:与自己交换(即保持不变),与第2位交换,与第3位交换
    • 然后固定第2位,有2个选择:与自己交换,与第3位交换
    • 固定最后一位,只有1个选择:与自己交换。因为前面2个位置已经固定,最后1位只能是剩下的那个

    总结规律
    这是一个递归的过程

    • 递推过程
      • 每一次需要将当前位置字符和后面的所有字符交换
      • 每一次待固定的位置向后移一位
    • 终止条件
      • 当固定到最后一位的时候,得到一个排列

    重复字符的处理

    设想输入的字符串当中包含了重复字符的情况,那么最后得到的结果也会有重复。如何解决这一问题呢?
    设当前位置的字符为,在当前位置与后边所有位的字符交换位置,假如在这个范围内(从当前位置到末尾的范围),有两个相同的字符,那么进行交换的结果是一样的。
    所以当第二次遇到某个字符时,就不必要再进行交换了,这个过程就是剪枝,下图很好的展示了这个过程。

    代码实现:
    维护一个HashSet变量,每次将遇到的字符存入,第二次遇到相同字符时,跳过本轮循环。

    解答

    class Solution {
        List<String> res = new LinkedList<>();
        char[] c;
        public String[] permutation(String s) {
            c = s.toCharArray();
            recur(0);
            //参数是为了指定返回数组的类型String[res.size()]
            return res.toArray(new String[res.size()]);
        }
        //在x位置处尝试所有可能的字符(和后边的所有字符交换位置)
        void recur(int x){
            //终止条件
            if(x == c.length - 1){
                res.add(String.valueOf(c));
                //递归终止
                return;
            }
            HashSet<Character> set = new HashSet<>();
            //递推过程:将x后面的所有字符交换到x处
            for(int i = x;i <= c.length - 1;i++){
                //在循环中,如果遇到重复字符,剪枝
                if(set.contains(c[i])) continue;
                //不是重复字符,则继续
                set.add(c[i]);
                swap(i,x);
                //开启递归子函数,去尝试下一位的所有可能
                recur(x+1);
                //恢复交换
                swap(i,x);
            }
        }
        //交换索引indexA和索引indexB位置的字符
        void swap(int indexA,int indexB){
            char tmp = c[indexA];
            c[indexA] = c[indexB];
            c[indexB] = tmp;
        }
    }
  • 相关阅读:
    此网页的安全性验证无效并且可能损坏的错误的解决方法
    fixSidebar简介与修正log
    Git可视化极简易教程 —— Git GUI使用方法
    windows平台快速搭建Linux(CentOS)
    CentOS在线安装Mysql5.7
    springboot集成mybatis(二)
    springboot测试、打包、部署
    springboot快速入门
    springboot集成mybatis(一)
    CentOS在线安装JDK
  • 原文地址:https://www.cnblogs.com/Howfars/p/13289445.html
Copyright © 2011-2022 走看看