今天的三道题都是递归算法。
题目一:没有重复项数字的全排列
题目描述:
给出一组数字,返回该组数字的所有排列
例如:
[1,2,3]的所有排列如下
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1].
(以数字在数组中的位置靠前为优先级,按字典序排列输出。)
输入输出描述:
输入:[1,2,3] 返回值:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
输入:[1] 返回值:[[1]]
思路解析:
保证每个元素能和从自己开始后的每个元素都交换位置,这种时候我们可以考虑递归和回溯。
step1: 处理特殊情况。
step 2:递归的时候从当前下标,遍历后续的元素,交换二者位置后,进入下一层递归。
step 3:处理完一分支的递归后,将交换的情况再换回来进行回溯,进入其他分支。
step 4:当前下标到达数组末尾就是一种排列情况。将数组转化为ArrayList,加入结果集里。
作答情况:
忘记进行回溯。
代码:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param num int整型一维数组
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> permute (int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
//特殊情况
if (num.length <= 0) return result;
AllSort(num, 0, num.length - 1, result);
// Arrays.sort(num);
return result;
}
public void AllSort(int[] num, int start, int end,
ArrayList<ArrayList<Integer>> result) {
for (int i = start; i <= end; i++) {
swap(num, i, start);
AllSort(num, start + 1, end, result);
swap(num, i, start);
}
if (start == end) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < num.length; i++) {
list.add(num[i]);
}
result.add(list);
}
}
public void swap(int[] num, int a, int b) {
int temp = num[a];
num[a] = num[b];
num[b] = temp;
}
}
题目二:有重复项数字的全排列
题目描述:
给出一组可能包含重复项的数字,返回该组数字的所有排列。结果以字典序升序排列。
数据范围: 0<n≤8 ,数组中的值满足 −1≤val≤5
输入输出描述:
输入:[1,1,2] 返回值:[[1,1,2],[1,2,1],[2,1,1]]
输入:[0,1] 返回值:[[0,1],[1,0]]
思路解析:
基于题目一“没有重复项数字的全排列”基础上,多了一步去重操作+重写字典序排序。
step1: 处理特殊情况。
step 2:递归之前实现Set接口,调用HashSet可以去重。递归的时候从当前下标,遍历后续的元素,交换二者位置后,进入下一层递归。
step 3:处理完一分支的递归后,将交换的情况再换回来进行回溯,进入其他分支。
step 4:当前下标到达数组末尾就是一种排列情况。将数组转化为ArrayList,加入结果集里。
step5: 因为可能存在负数,所以重写Collectons.sort()自定义排序顺序,这里是升序。
作答情况:
①这一步总是会写错,要牢记。
②按字典序升序的时候,直接使用Arrays.sort();这里疏忽了数组中的值满足 −1≤val≤5,存在负数,字典序只是针对于正数,所以这里要重写字典序排序得以解决。
重写字典序(升序):
代码:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param num int整型一维数组
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) {
ArrayList<ArrayList<Integer>> result=new ArrayList<>();
if(num.length<=0) return result;
AllSort(num,0,num.length-1,result);
Collections.sort(result,new Comparator<ArrayList<Integer>>(){
public int compare(ArrayList<Integer> list1,ArrayList<Integer> list2){
for(int i=0;i<list1.size();i++){
if(list1.get(i)!=list2.get(i)){
return list1.get(i)-list2.get(i);
}
}
return 0;
}
});
return result;
}
public void AllSort(int[] num,int start,int end,ArrayList<ArrayList<Integer>> result){
HashSet<Integer> set=new HashSet<>();
for(int i=start;i<=end;i++){
if(i==start||!set.contains(num[i])){
set.add(num[i]);
swap(num,i,start);
AllSort(num,start+1,end,result);
swap(num,i,start);
}
}
if(start==end){
ArrayList<Integer> list=new ArrayList<>();
for(int i=0;i<num.length;i++){
list.add(num[i]);
}
result.add(list);
}
}
public void swap(int[] num,int a,int b){
int temp=num[a];
num[a]=num[b];
num[b]=temp;
}
}
题目三:字符串的排列(答案没有重复项)
题目描述:
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
输入输出描述:
输入:"ab" 返回值:["ab","ba"] 返回["ba","ab"]也是正确的
输入:"aab" 返回值:["aab","aba","baa"]
思路解析:
递归与回溯+使用set去重
step1: 处理特殊情况。
step 2:递归之前实现Set接口,调用HashSet可以去重。递归的时候从当前下标,遍历后续的元素,交换二者位置后,进入下一层递归。
step 3:处理完一分支的递归后,将交换的情况再换回来进行回溯,进入其他分支。
step 4:当前下标到达数组末尾就是一种排列情况。将字符串数组通过强制类型转换为字符串,加入结果集里。
作答情况:
又忘了写
代码:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> Permutation (String str) {
ArrayList<String> result=new ArrayList<>();
//将字符串转换为字符数组
char[] chars=str.toCharArray();
//全排列
AllSort(chars,0,chars.length-1,result);
return result;
}
public void AllSort(char[] chars,int start,int end,ArrayList<String> result){
Set<Character> set=new HashSet<>();
for(int i=start;i<=end;i++){
if(i==start||!set.contains(chars[i])){
//不要遗忘
set.add(chars[i]);
//交换
swap(chars,i,start);
AllSort(chars,start+1,end,result);
//回溯
swap(chars,i,start);
}
}
if(start==end){
//将字符串数组转化为字符串
result.add(String.valueOf(chars));
}
}
public void swap(char[] chars,int a,int b){
char temp=chars[a];
chars[a]=chars[b];
chars[b]=temp;
}
}
收获:
Collections.sort()专门给List排序,Arrays.sort()专门给数组排序。