Day27:字符串的排列

时间:2022-07-24
本文章向大家介绍Day27:字符串的排列,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

剑指Offer_编程题——字符串的排列

题目描述:

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符串a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab,cba。

输入描述

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

具体要求:

时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M

具体思路:

思路一   这也是我们经常想到的思路,也就是固定交换法。即:先固定一个字母不变,通常固定在子串的首位,如abc固定a,对bc再进行全排列,bc串中固定b,对c进行全排列。交换即在a固定的情况下已经对bc子串进行了全排列之后,那么就将a与第二位的b交换变成bac,此时再回到了固定的步骤,只需固定b,对字串ac进行全排列。依此类推,直至交换完。这个是好想,但是有一个小坑需要我们注意,那就是有重复元素的情况,如aab,那么只需加一个判定条件,当交换的元素相同就无需进行交换,直接跳过即可。我们用python来实现这一思路。

class Solution:
	def Permutation(self, ss):
		if not ss or not len(ss):
			return ss
		self.res = []
		self.permutation(list(ss), 0, len(ss))
		return sorted(self.res)
	def permutation(self, ss, index, length):
		if length - 1 == index:
			self.res.append(''.join(ss))
			return
		for i in range(index, length):
			if (ss[i] == ss[index] and i != index):
				continue
			a = ss[i]
			ss[i] = ss[index]
			ss[index] = a
			self.permutation(ss, index + 1, length)
			a = ss[i]
			ss[i] = ss[index]
			ss[index] = a
		return

代码效果图如图所示:

思路二   列出所有字符串用递归求解,对于n个字符串的排列问题,如果能生成n-1个元素的全部排列结果,就能生成n个元素的全部排列结果。接下来我们用Java来实现比较方便。由于java中专门有一个排序集合——TreeSet。又因为题目中要求返回ArrayList类型,故将TreeSet中的元素全部加入到ArrayList中。

import java.util.*;
public class Solution{
   public ArrayList<String> Permutation(String str){
   	 ArrayList<String> result = new ArrayList<String>();
   	 if(str == null || str.length() == 0){
   	 	return result;
   	 }
   	 char[] chars = str.toCharArray();
   	 TreeSet<String> res = new TreeSet<String>();
   	 getResult(chars, 0, str.length() - 1, res);
   	 result.addAll(res);
   	 return result;
   }
   public void getResult(char[] chars, int start, int end, TreeSet<String> res){
   	if(start == end){
   		res.add(String.valueOf(chars));
   	}else{
   		for(int i = start; i <= end; i++){
   			swap(chars, start, i);
   			getResult(chars, start + 1, end, res);
   			swap(chars, start, i);
   		}
   	}
   }
   public void swap(char[] chars, int a, int b){
   	if(a == b){
   	
   	}else{
   		char temp = chars[a];
   		chars[a] = chars[b];
   		chars[b] = temp;
   	}
   }
}

代码效果图如图所示:

思路三   这种想法是最难想到的,但是代码量以及运行效果确实最优的。留一排他法:留一即将一位留出来,排他即将剩下的进行全排列,然后将留出来的分别拼到全排列串的首位。如abc,留a,排bc得bc、cb,拼:a+bc,a+cb,结果,abc,acb。再留b,排ac……依此类推。具体我们用python将其实现

class Solution:
	def Permutation(self, ss):
		if len(ss) == 0:
			return []
		if len(ss) == 1:
			return [ss]
		res = set()
		for i in range(len(ss)):
			for j in self.Permutation(ss[:i] + ss[i+1:]):
				res.add(ss[i] + j)
		return sorted(res)

代码效果图如图所示:

总结

  本道题主要考察字符串的排序,这里考察的知识点是字符串以及动态规划和递归的相关知识。我们首先想到的思路就是固定一个字母,然后遍历调换其他两个字母,这里有一个小坑就是当字符重复的时候,直接跳过交换。思路二是用到了我们Java中的TreeSet有序集合。大大降低了难度。不过我们题目要求的是返回ArrayList,因此我们还需要将TreeSet集合的元素再放入到ArrayList中。思路三是不好想,但是效果最佳,应用的留一排他法,大大减少了代码量和运行时间。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!

参考文献

[1] lingongheng [2] Valonecium