剑指offer 字符串的排列原题,java实现,组合排列去重

xiaoxiao2021-02-28  44

首先讲一下原理:

求字符串的排列,可以看成两步:1、把所有可能的字符都放在第一位,具体实现:可以遍历一次字符串,从第一个字符开始与第一个字符互唤,一次遍历后所有字符都会一次出现在第一个位置。在每次循环内实现第二步。2、将剩余的字符串的所有可能的字符放到该剩余字符串的位置(即重复1)。然后进行第三步,将原先互换的字符再次互换回来,恢复原始顺序,一遍进行后续的互换。过程图如下:

假设字符串char[] c={'a','b','c'};

1)第一次互换结果是:a,b,c(因为是从第一个字符开始与第一个字符互换的);//第一步

2)剩余字符串为"bc",执行第一次互换,结果"bc",剩余字符串"c"继续互换,因为是最后字符,所以排列结束,最后输出“abc”(排列组合结果之一);输出之后,剩余字符串恢复原始顺序到"bc",然后'b'与'c'互换,此时已经到了最后一个字符'b',输出"acb";

"abc"(第1位与第1位互换)->"abc"(第2位与第2位互换)->"abc"

"abc"(第1位与第1位互换)->"acb"(第2位与第3位互换)->"acb"

"abc"(第1位与第2位互换)->"bac"(第2位与第2位互换)->"bac"

"abc"(第1位与第2位互换)->"bac"(第2位与第3位互换)->"bca"

"abc"(第1位与第3位互换)->"cba"(第2位与第2位互换)->"cba"

"abc"(第1位与第3位互换)->"cba"(第2位与第3位互换)->"cab"

JAVA源代码如下,已经编译过,木有问题,注意主类名即可

package test; import java.util.*; class CombinationArrangement1{ private char[] input; //private List<String> result; private String tempStr=null; private int len; CombinationArrangement1(char[] input){ this.input=input; this.len=input.length; } /*开始组合排列,并将每次打印结果放入result中 * 一次组合完后立即恢复原始顺序 * @Author fishing_fly * */ void startArrange(int startIndex){ if(startIndex==len){ tempStr=String.valueOf(input); System.out.println(tempStr); //result.add(tempStr); tempStr=null; return; } for(int i=startIndex;i<len;i++){ swap(i,startIndex);//第一步交换 startArrange(startIndex+1);//第二步剩余字符串递归执行排列组合操作 swap(i,startIndex);//第三部恢复当前循环原始字符串 } // display(); } void swap(int first,int second){ char temp; temp=input[first]; input[first]=input[second]; input[second]=temp; } // void display(){ // Iterator iter=result.iterator(); // while(iter.hasNext()){ // System.out.print(iter.next()+"->"); // } // System.out.println(); // } } public class Solution { public static void main(String[] args){ char[] temp={'a','b','c'}; CombinationArrangement1 c=new CombinationArrangement1(temp); c.startArrange(0);; } }

*注意,若是原始字符串中有相同字符,则组合结果会出现以下相同结果,避免此类结果的方法是:执行互换时判断一下要调换到第一个位置的那个字符之前有没有字符和它是一样的,一样continue执行下次循环,不一样继续执行交换;

因为:

 “baa”(原始字符串)->"aba"(第1位与第2位互换)->"aba"(第2位与第2位互换)

     ->"aba"(第1位与第2位互换)->"aab"(第2位与第3位互换)

“baa”->"aba"(第1位与第3位互换)->"aba"(第2位与第2位互换)

  ->"aba"(第1位与第3位互换)->"aab"(第2位与第3位互换)

因为第二位和第三位是一样的,导致最后它们的排列结果是一样的,所以去重时要判断前面已经有相同得字符被互换过,就不用再次互换了

package test; import java.util.*; class CombinationArrangement1{ private char[] input; //private List<String> result; private String tempStr=null; private int len; CombinationArrangement1(char[] input){ this.input=input; this.len=input.length; } /*开始组合排列,并将每次打印结果放入result中 * 一次组合完后立即恢复原始顺序 * @Author fishing_fly * */ public void startArrange(int startIndex){ if(startIndex==len){ tempStr=String.valueOf(input); System.out.println(tempStr); //result.add(tempStr); tempStr=null; return; } for(int i=startIndex;i<len;i++){ if(IsSwap(startIndex,i)) continue; swap(i,startIndex); startArrange(startIndex+1); swap(i,startIndex); } // display(); } public void swap(int first,int second){ char temp; temp=input[first]; input[first]=input[second]; input[second]=temp; } private boolean IsSwap(int first,int second){ boolean result=false; for(int i=first;i<second;i++){ if(input[i]==input[second]){ return true; } } return result; } } public class Solution { public static void main(String[] args){ char[] temp={'a','b','c','a'}; CombinationArrangement1 c=new CombinationArrangement1(temp); c.startArrange(0);; } }

转载请注明原文地址: https://www.6miu.com/read-600018.html

最新回复(0)