剑指offer第二版——面试题38(java)

面试题:字符串的排序

题目:

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

例如:输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba

思路:

对一个字符串进行全排列可分为两个问题:1.选择第一个位置的字符串;2. 对后面的子字符串进行全排列

递归过程

如长度为3的字符串,先固定第一个字符串,再对后面的长度为2的字符串进行全排列,即固定长度为2的字符串中的第一个位置,再对剩下长度为1的字符串进行全排列,此时输出排列的字符串

【注意】在对长度为n的字符串全排列时,会将第i个位置的字符与首位字符交换,在此次全排列结束后,需要将第i个位置的字符与首位字符换回来

举例:

对字符串abc来说,有三个字符,使用for循环来依次将三个字符都放在此时排列的字符串的第一个位置

(3长度循环)1. 先将a放在第一个位置,此时子字符串为bc,进入对bc的排列(for循环从i=0到i=len,会依次将第i个字符与第一个字符进行交换,使第i个字符被放到最前面,下面放置同理)

(2长度循环)a.子字符串bc中,先将b放在第一个位置,对c进行排列

              (1长度循环)i.子字符串c中,此时将c放在第一个位置(abc),对空字符串进行排列

         ·待排字符串为空,打印当前字符串abc返回到将c放在第一位置的操作,将c返回到交换前的状态,以不妨碍之后元素的交换(abc)

              (1长度循环)ii.  c之后没有下一个元素,因此返回到2中,将b返回交换前的状态(abc)

(2长度循环)b.子字符串bc中,现将c放到第一个位置,即交换c和第一个位置的字符(acb)

              (1长度循环)i.  字符串b中,将b放在第一个位置,对空字符串进行排序

              ·待排字符串为空,打印当前字符串(acb), 退回7中,还原为bc

(2长度循环)无其他元素可进行排序,返回3长度循环中顺序(abc),还原a的调换(a与a的交换)

(3长度循环)2. 在字符串abc中,已将第一个元素放在首位,现将第二个元素放在首位,即b与首位字符交换(bac)

(2长度循环)a.在字符串ac中,先将a放在首位

              (1长度循环)i.在字符串c中,将c放在首位

              ·在空字符串中,打印当前字符串(bac),返回字符串c中,无字符可排序,还原;返回字符ac中,还原

(2长度循环)b. 将c放在首位,交换位置(bca)

              (1长度循环)i.在字符串a中,先将a放在首位

              ·在空字符串中,打印当前字符串(bca)

              (1长度循环)ii.在字符串a中,无其他字符可排序,还原;

(2长度循环)c.返回字符ca中,无其他字符可排序,还原ca为ac;

第三个循环同理……

【注意】

如果面试需要按照一定要求摆放若干个数字,则可以先求出这些数字的所有排列,然后进行一一判断

【代码】

public class Q38 {
	public static void main(String[] args) {
		char[] array = new char[] {'a','b','c'};
		permutation(array,0);
	}
	
	public static void permutation(char[] array,int start) {
		if(array.length<0) {
			return;
		}
		
		if(start == array.length) {
			System.out.println(array);
		}
		
		for(int i=start;i<array.length;i++) {
			swap(array, i, start);
			permutation(array,start+1);
			swap(array, start, i);
		}
	}
	
	public static void swap(char[] array,int i,int j) {
		char temp = array[j];
		array[j] = array[i];
		array[i] = temp;
	}
}

【本题扩展】

求字符的所有组合

也是用递归完成

每次子串组合可分为两部分:组合中包含第一个字符/组合中不包含第一个字符

组合中包含第一个字符,则从子串后面选n-1个,

组合中不包含第一个字符,则从子串后面选n个

【代码】

	public static void main(String[] args) {
		char[] array = new char[] {'a','b','c','d'};
		for(int i=0;i<array.length;i++) {
			System.out.printf("len of subString:%d\n",i);
			combinat(array,0,i,new StringBuffer());
		}
	}

	public static void combinat(char[] array,int start,int i,StringBuffer stb) {
		if(i==0) {
			System.out.println(stb);
			return;
		}
		
		if(start==array.length) {
			return;
		}
		
		stb.append(array[start]);
		combinat(array, start+1, i-1, stb);
		stb.deleteCharAt(stb.length()-1);
		combinat(array, start+1, i, stb);
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值