【剑指offer】38. 字符串的排列

129 阅读1分钟

题目描述

在这里插入图片描述 在这里插入图片描述

// 力扣
// 输入一个字符串,打印出该字符串中字符的所有排列。
// 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。


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

题解

/////////////////////////////////////////// 递归回溯法 ////////////////////////////////////

// 牛客
// 运行时间:73ms
// 占用内存:12272k
import java.util.ArrayList;
public class Solution {
	// 定义ArrayList作答案存储字符组
	ArrayList<String> res = new ArrayList<>();  

    public ArrayList<String> Permutation(String str) {
		if (str.length() == 0)  // 如果输入是空,直接返回res
			return res;
		char[] char_array = str.toCharArray();  // str转为char[]
		// 定义boolean[]用于记录某字符是否被使用过
		boolean[] used = new boolean[str.length()];
		// 定义StringBuilder temp来存储当前字符的组成
		StringBuilder temp = new StringBuilder();
		// 调用递归函数
		backtrack(char_array, used, temp);
		return res;
    }
	
	// 字符组形式的char_array用于字母元素遍历
	// bool值组的used用于记录对应索引上char_array元素是否用过
	// StringBuilder的temp用于保存当前组合出来的字符
	private void backtrack(char[] char_array, boolean[] used, StringBuilder temp) {
		// 如果匹配出的字符temp长度与char_array长度相同,说明字符匹配完成
		// 返回(递归回溯)
		if (temp.length() == char_array.length) {
			res.add(temp.toString());
			return;
		}
		// for循环遍历char_array中的字符(可用于匹配的元素)、
		// 遍历索引为i
		for (int i = 0; i < char_array.length; i++) {
			// 如果当前元素用过,当前for循环跳过,进入下一次for循环
			if (used[i])
				continue;
			// 如果遍历字符非首字符,且当前遍历字符与前一字符相等
			// 且前一字符未被用过(或用过后已回溯,被重新标记未使用)
			// ,当前for循环跳过,进入下一次for循环
			if (i != 0 && char_array[i] == char_array[i - 1] && !used[i - 1]) 
				continue;
			used[i] = true;  // 标记i索引位字符已使用
			temp.append(char_array[i]);  // 如果字符符合条件,append进去
			// 递归调用,继续排列temp字符组合,直到排出的字符串长度达到上限
			backtrack(char_array, used, temp);
			// 递归出来,删除刚刚已经使用过的字符(下一个for使用下一个字符)
			temp.deleteCharAt(temp.length() - 1);  
			used[i] = false;  // 回溯后,i索引位字符标记为未使用
		}
	}
}


// 力扣
// 执行用时:11 ms, 在所有 Java 提交中击败了64.52%的用户
// 内存消耗:42.8 MB, 在所有 Java 提交中击败了77.37%的用户
import java.util.ArrayList;
class Solution {
	ArrayList<String> res = new ArrayList<>();

    public String[] permutation(String s) {
        if (s.length() == 0)
			return new String[0];
		char[] char_array = s.toCharArray();
		boolean[] used = new boolean[s.length()];
		StringBuilder temp = new StringBuilder();
		Arrays.sort(char_array);  // 力扣一定要加升序,不然过不了!!!
		backtrack(char_array, used, temp);
        String[] result = (String[]) res.toArray(new String[res.size]);
		return result;
    }
	
	private void backtrack(char[] char_array, boolean[] used, StringBuilder temp) {
		if (temp.length() == char_array.length) {
			res.add(temp.toString());
			return;
		}
		for (int i = 0; i < char_array.length; i++) {
			if (used[i])
				continue;
			if (i != 0 && char_array[i] == char_array[i - 1] && !used[i - 1])
				continue;
			used[i] = true;
			temp.append(char_array[i]);
			backtrack(char_array, used, temp);
			temp.deleteCharAt(temp.length() - 1);
			used[i] = false;
		}
	}
}