字符串的排列

1:题目描述

输入一个字符串,打印出该字符串中字符的所有排列。

 

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

 

示例:

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

限制:

1 <= s 的长度 <= 8

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2:题目分析

首先这是一道全排序的问题,同时要求使用不能重复,所以我们采用dfs深度搜索和set集合去重的方法来解决这个问题。关键点在于dfs深度搜索如何设计?

  我们直到在图中使用dfs时,是对所有顶点都遍历一遍才能结束,然后这里的dfs是针对每次路径都要不重复的,与图的深度搜索是由很大差异的。为了简单期间我们先手工推算出如果是3个字符的字符串应该如何处理?然后从特殊到一般的来进行迭代算法的分析:

假设字符串为:a,b,c三个字符串,我们通过以下方法可以判断出来如何获得其排序的结果。

第一次循环:在a,b,c中选择某一个没有标记的字符,标记为选择状态,然后加入StringBuilder中。然后进入

第二次循环:选择某一个没有标记的字符,标记为选择状态,然后加入StringBuilder中。然后进入

第三次循环:选择某一个没有标记的字符,标记为选择状态,然后加入StringBuilder中,然后将StringBulider记过保存在输出Stirng[]。然后同时将本轮标记的字符清除标记,同时StringBuilder也取出本次的获取的字符。退出第三次循环,计入上次循环即为第二次循环,然后依然清除当前标记,退出当前字符,在第二次进行下一次找的的字符。重读本次操作,依然在找到下一次字符后会进去第三次循环,直到第二和第三次循环结束,再进行第一次循环中,遍历处理。

3:代码示例

package JianZhiOffer38;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashSet;

/**
 * @author :dazhu
 * @date :Created in 2020/3/24 8:04
 * @description:剑指offer38
 * @modified By:
 * @version: $
 */
public class Main {
    public static void main(String[]args){
        Solution solution = new Solution();
        String s ="aab";
        solution.permutation(s);
    }
}
class Solution {
    StringBuilder sResult ;
    String s;
    int[] mark;
    int sum=0;
    int lastIndex=0;
    //使用HashSet可以去重
    HashSet<String> hs = new HashSet<>();
    int slength=0;
    //做法从特殊到一般的思想,慢慢解决。
    public String[] permutation(String s) {
        this.s = s;
        this.sResult =new StringBuilder(s.length());
        this.mark = new int[s.length()];
        this.slength = s.length();
        recur();

        return hs.toArray(new String[hs.size()]);//集合转数组
    }
    //把上面的从特殊到一般的算法,用迭代的方法计算即可
    //迭代终止条件:迭代到了最后一个字符,则终止迭代,将该字符加入字符串然后将获得取得完整字符串往ArratList中存。
    //迭代逻辑:标记当前选取的字符,然后再次迭代判断下次选择的字符,当退出迭代时,将本次标记清零
    //返回值:void
    void recur(){
        //**********迭代终止条件和处理**************
        //判断是不是只有剩下一个字符了?
        sum = 0;
        for(int i=0;i<slength;i++){
            sum = sum + mark[i];
            //将最后一个为0的字符位置保存起来。
            if(mark[i] == 0){
                lastIndex = i;
            }
        }
        //如果mark之和为length-1,则只有一个字符没有被选择了。
        //则将此时的字符串放入ArrayList中来。
        if(sum == slength-1){
            //把最后一个字符加入。
            sResult.append(s.charAt(lastIndex));
            //String temp = new String(""+sResult);
            hs.add(""+sResult);
            //在取出最后一个字符。
            sResult.deleteCharAt(sResult.length()-1);
            return ;
        }
        //************迭代逻辑**************
        for(int i=0;i<slength;i++){
            //只有当该字符没有被标记,才能选择。
            if(mark[i]==0) {
                //将当字符标记为1,意味着选择该字符。
                mark[i] = 1;
                //将该字符加入指定字符串,供输出使用。
                sResult.append(s.charAt(i));
                //再继续迭代下去
                recur();
                //递归回来时,将本次加入的字符取出,供后序使用,
                sResult.deleteCharAt(sResult.length()-1);
                //该字符选择后,当递归回来时,应该将该字符重新标记0,为本次循环向后执行时
                //能够继续选取本字符。
                mark[i] = 0;
            }
        }
    }
}

 

posted @ 2020-03-24 11:09  大朱123  阅读(252)  评论(0)    收藏  举报