字符串全排列算法学习总结

这里写图片描述
刷题遇到了这个全排列的算法题目,头好疼,整理下各种算法。
学习了这个博主的文章,感谢感谢http://www.cnblogs.com/cxjchen/p/3932949.html
1、递归算法
这里写图片描述

对于无重复值的情况 :
固定第一个字符,递归取得首位后面的各种字符串组合;
再把第一个字符与后面每一个字符交换,并同样递归获得首位后面的字符串组合;
递归的出口,就是只剩一个字符的时候,递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串。

如有重复值呢?
对于abb,第一个数a与第二个数b交换得到bab,然后考虑第一个数与第三个数交换,此时由于第三个数等于第二个数, 所以第一个数就不再用与第三个数交换了。再考虑bab,它的第二个数与第三个数交换可以解决bba,即可。

import java.util.*;
public class Solution {
     ArrayList<String> a =new ArrayList<String>();

    public ArrayList<String> Permutation(String str) {

        if(str.length()>0&&str!=null)
           {
            Per(str.toCharArray(),0,a);
            Collections.sort(a);

        }
        return a;
    }

        private void Per(char[] chars,int i,ArrayList<String> a)
            {
            if(i==chars.length-1)
                a.add(String.valueOf(chars));
            else{

                Set<Character> charset =new HashSet<Character>();
                for(int j=i;j<chars.length;++j)
                    {
                    if(j==i||!charset.contains(chars[j]))
                        {
                        charset.add(chars[j]);
                        swap(chars,i,j);
                        Per(chars ,i+1,a);
                        swap(chars,j,i); 
                    }
                }
            }  
        }
        public void swap(char[]c ,int i,int j)
            {
            char temp=c[i];
            c[i]=c[j];
            c[j]=temp;

        }

}

2、字典序排列算法
学习了http://www.cnblogs.com/pmars/archive/2013/12/04/3458289.html  感谢作者~
以及牛客网作者天天502
https://www.nowcoder.com/questionTerminal/fe6b651b66ae47d7acce78ffdd9a96c7

固定第一个字符,递归取得首位后面的各种字符串组合;  再把第一个字符与后面每一个字符交换,并同样递归获得首位后面的字符串组合; 
递归的出口,就是只剩一个字符的时候,递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串。     
一个全排列可看做一个字符串,字符串可有前缀、后缀。 生成给定全排列的下一个排列.所谓一个的下一个就是这一个与下一个之间没有其他的。 这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。    
     [例]8396475211--9的排列。19的排列最前面的是123456789,最后面的987654321, 从右向左扫描若都是增的,就到了987654321,也就没有下一个了。否则找出第一次出现下降的位置。  
    【例】 如何得到346987521的下一个     
     1、从尾部往前找第一个P(i-1) < P(i)的位置     
      3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1     
      最终找到6是第一个变小的数字,记录下6的位置i-1     
     2、从i位置往后找到最后一个大于6的数     
       3 4 6 -> 9 -> 8 -> 7 5 2 1     
       最终找到7的位置,记录位置为m    
     3、交换位置i-1和m的值     
        3 4 7 9 8 6 5 2 1     
     4、倒序i位置后的所有数据     
       3 4 7 1 2 5 6 8 9347125689346987521的下一个排列

public ArrayList<String> Per2(String str)
{
    ArrayList<String> a = new ArrayList<String>();
    if(str==null|| str.length()==0)
    {
        return a;
    }
    char[] chars=str.toCharArray();
    Arrays.sort(chars);
    a.add(String.valueOf(chars));
    int len=chars.length;
while(true)
    {
        int lIndex = len-1;
        int rIndex;
        while(lIndex>=1&&chars[lIndex-1]>=chars[lIndex])
        {
            lIndex--;
        }
if(lIndex==0)
            break;
        rIndex=lIndex;
        while(rIndex<len&&chars[rIndex]>chars[lIndex-1])
        {
            rIndex++;
        }
        swap(chars,lIndex-1,rIndex-1);
        reverse(chars,lIndex);
        a.add(String.valueOf(chars));

    }
    return a;
}
private void reverse(char[] chars, int k)
{
    if(chars==null|| chars.length<=k)
        return;
    int len=chars.length;
    for(int i=0;i<(len-k)/2;i++)
    {
        int m =k+i;
        int n=len-1-i;
        if(m<=n)
            swap(chars,m,n);
    }

  }

看的好晕~~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值