写在前面:
求解排列问题常用的方法是回溯,回溯类似于DFS(深度优先遍历),实际是一个暴力搜索的过程,把所有的排列都列举出来,找出符合题意的排列。组合问题与元素顺序无关,而排列问题与元素的顺序有关。
1、46. Permutations
题意:
给出一个不含重复元素的数组,求所有可能的排列。
代码:
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
backtrack(res,new ArrayList<>(),nums);
return res;
}
public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums){
if(list.size()==nums.length){
res.add(new ArrayList<>(list));
}
for(int i=0;i<nums.length;i++){
if(list.contains(nums[i])){
continue;
}
list.add(nums[i]);
backtrack(res,list,nums);
list.remove(list.size()-1);
}
}
}
2、47. Permutations II
题意:
给出一个可能含重复元素的数组,求所有可能的排列。
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
Arrays.sort(nums);
boolean[] visited=new boolean[nums.length];
backtrack(res,new ArrayList<>(),nums,visited);
return res;
}
public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums,boolean[] visited){
if(list.size()==nums.length){
res.add(new ArrayList<>(list));
}
for(int i=0;i<nums.length;i++){
if(visited[i]){
continue;
}
if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]){
continue;
//这一步的剪枝参考https://leetcode-cn.com/problems/combination-sum-ii/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-3/
}
visited[i]=true;
list.add(nums[i]);
backtrack(res,list,nums,visited);
list.remove(list.size()-1);
visited[i]=false;
}
}
}
3、996. Number of Squareful Arrays
题意
给出一个可能含重复元素的数组,求满足相邻元素之和为平方数的排列的数量。
class Solution {
public int numSquarefulPerms(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
Arrays.sort(nums);
boolean[] visited=new boolean[nums.length];
backtrack(res,new ArrayList<>(),nums,visited);
return res.size();
}
public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums,boolean[] visited){
if(list.size()==nums.length){
res.add(new ArrayList<>(list));
}
for(int i=0;i<nums.length;i++){
if(visited[i]){
continue;
}
if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]){
continue;
}
if(!list.isEmpty()&&isPerfectSquare(nums[i]+list.get(list.size()-1)) || list.isEmpty()){
visited[i]=true;
list.add(nums[i]);
backtrack(res,list,nums,visited);
list.remove(list.size()-1);
visited[i]=false;
}
}
}
public void backtrack(List<List<Integer>> res,List<Integer> list,int[] nums){
if(list.size()==nums.length){
res.add(new ArrayList<>(list));
return;
}
for(int i=0;i<nums.length;i++){
if(list.contains(nums[i])){
continue;
}
if(!list.isEmpty()&&isPerfectSquare(nums[i]+list.get(list.size()-1)) || list.isEmpty()){
list.add(nums[i]);
backtrack(res,list,nums);
list.remove(list.size()-1);
}
}
}
public boolean isPerfectSquare(int n){
if((int)Math.sqrt(n)*(int)Math.sqrt(n)==n){
return true;
}
return false;
}
}