爱奇艺2道编程笔试题目小结

第一道题目:字符串的全排列问题

pf:
input:abc
output:
abc
acb
bac
bca
cab
cba
(注意这里暗指输出是有序的。)

解法:
递归过程如下:
这里写图片描述
具体

package aiqiyi;
import java.util.Scanner;
import java.util.TreeSet;

/**
 * Created by lcq on 2016/9/27.
 */
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            TreeSet<String> set = new TreeSet<>();
            String input = sc.nextLine();
            char[] buf = input.toCharArray();
            permutation(buf,0,buf.length-1,set);
            for(String str:set){
                System.out.println(str);
            }
        }
    }

    public static  void permutation(char[] buf, int start, int end,TreeSet<String>set) {
        if (start == end) {// 当只要求对数组中一个字母进行全排列时,只要就按该数组输出即可
            System.out.println(new String(buf)+set.size());
            set.add(new String(buf));
        } else {// 多个字母全排列
            for (int i = start; i <= end; i++) {
                char temp = buf[start];// 交换数组第一个元素与后续的元素
                buf[start] = buf[i];
                buf[i] = temp;
                permutation(buf, start + 1, end,set);// 后续元素递归全排列
                temp = buf[start];// 将交换后的数组还原
                buf[start] = buf[i];
                buf[i] = temp;
            }
        }
    }
}

另外这种全排列字符串的方法对于abb形式的字符串会产生重复结果,因此需要去重。
去重的原则:
由于全排列就是从第一个数字起,每个数分别与它后面的数字交换,我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这两个数就不交换 了。例如abb,第一个数与后面两个数交换得bab,bba。然后abb中第二个数和第三个数相同,就不用交换了。但是对bab,第二个数和第三个数不 同,则需要交换,得到bba。由于这里的bba和开始第一个数与第三个数交换的结果相同了,因此这个方法不行。

换种思维,对abb,第一个数a与第二个数b交换得到bab,然后考虑第一个数与第三个数交换,此时由于第三个数等于第二个数,所以第一个数就不再用与第三个数交换了。再考虑bab,它的第二个数与第三个数交换可以解决bba。此时全排列生成完毕!

这样,我们得到在全排列中去掉重复的规则:
去重的全排列就是从第一个数字起,每个数分别与它后面非重复出现的数字交换。
即对于abb,a与第一个数b交换后就不需要与第二个b进行交换了。

public static  void permutation(char[] buf, int start, int end) {
        if (start == end) {//打印输出   
            System.out.println(new String(buf));
        } else {// 多个字母全排列
                for (int i = start; i <= end; i++) {
                  if(is_swap(start,i,buf)){  //是否有重复,进行交换;
                    char temp = buf[start];// 交换数组第一个元素与后续的元素
                    buf[start] = buf[i];
                    buf[i] = temp;
                    permutation(buf, start + 1, end,set);// 后续元素递归全排列
                    temp = buf[start];// 将交换后的数组还原
                    buf[start] = buf[i];
                    buf[i] = temp;
              }
           }
        }
    }
}

public boolean is_swap(int start,int k,char[] buf){
    boolean flag = true;
    for(int i = start;i < k;++i){
       if(buf[start] == buf[k]){
          flag = false;
          break;
       }
    }
    return flag;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值