题目及测试
package pid046;
import java.util.List;
/*全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
*/
public class main {
public static void main(String[] args) {
int[] testTable=new int[]{1,2,3,4};
test(testTable);
}
private static void test(int[] ito) {
Solution solution = new Solution();
int length=ito.length;
List<List<Integer>> rtn;
for(int i=0;i<length;i++){
System.out.print( ito[i]+" ");
}
System.out.println();
long begin = System.currentTimeMillis();
rtn=solution.permute(ito);//执行程序
long end = System.currentTimeMillis();
for(int i=0;i<rtn.size();i++){
for(int j=0;j<rtn.get(i).size();j++){
System.out.print( rtn.get(i).get(j)+" ");
}
System.out.println();
}
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,8ms,较慢)
在类中建立一个result的变量,放置结果
建立permutateRemain函数,变量为上一次的全排列几位的list(now)和还能排的数字的list(remain)
在函数中,
如果remain剩余的量为0,将now加入result
对remain进行遍历,在遍历中
遍历的数字为now
先建立一个对now的copy newlist,将newlist加入now
然后将remain除去now,进行新的permutateRemain,然后在remain重新加入now,结束遍历
package pid046;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class Solution {
List<List<Integer>> result=new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
int length=nums.length;
if(length==0){
return result;
}
List<Integer> now=new ArrayList<>();
List<Integer> remain=new ArrayList<>(nums.length);
for(int num:nums){
remain.add(num);
}
permuteRemain(now,remain);
return result;
}
public void permuteRemain(List<Integer> now,List<Integer> remain){
if(remain.size()==0){
result.add(now);
return;
}
List<Integer> newList;
for(int i=0;i<remain.size();i++){
Integer num=remain.get(i);
remain.remove(i);
newList=new ArrayList<>();
newList.addAll(now);
newList.add(num);
permuteRemain(newList, remain);
remain.add(i, num);
}
}
}
解法2(成功,6ms,较慢)
解法大概一致,但是remainSet进行遍历时,不能进行add,remove操作,所以toArray了,浪费了时间
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result=new ArrayList<>();
Set<Integer> remainSet=new HashSet<>(nums.length);
for(int num:nums){
remainSet.add(num);
}
//这个list作为公共的list,如果确认是要加入result的,复制一个新的出来
List<Integer> nowList=new ArrayList<>(nums.length);
combine(result, nowList, remainSet);
return result;
}
public void combine(List<List<Integer>> result,List<Integer> nowList,Set<Integer> remainSet){
if(remainSet.isEmpty()){
copyListIntoResult(result,nowList);
}
for(Integer num:remainSet.toArray(new Integer[]{})){
nowList.add(num);
remainSet.remove(num);
combine(result, nowList, remainSet);
nowList.remove(nowList.size()-1);
remainSet.add(num);
}
}
public void copyListIntoResult(List<List<Integer>> result,List<Integer> nowList){
List<Integer> newList=new ArrayList<>(nowList.size());
for(Integer num:nowList){
newList.add(num);
}
result.add(newList);
}
解法3(成功,2ms,较快)
不用hashset作为剩余集合,用ArrayList,传入指标,将first与first之后的数字一一交换,从而遍历。
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result=new ArrayList<>();
//这个list作为公共的list,如果确认是要加入result的,复制一个新的出来
List<Integer> nowList=new ArrayList<>(nums.length);
combine(result, nowList, nums,0);
return result;
}
public void combine(List<List<Integer>> result,List<Integer> nowList,int[] nums,int index) {
if(index == nums.length) {
copyListIntoResult(result, nowList);
return;
}
for(int i=index;i<nums.length;i++) {
swap(nums, index, i);
nowList.add(nums[index]);
combine(result, nowList, nums, index+1);
nowList.remove(nowList.size() - 1);
swap(nums, index, i);
}
}
public void copyListIntoResult(List<List<Integer>> result,List<Integer> nowList){
List<Integer> newList=new ArrayList<>(nowList.size());
for(Integer num:nowList){
newList.add(num);
}
result.add(newList);
}
public void swap(int[] nums,int i,int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
解法4(别人的)
创建一个visited数组,来得到哪个数字已经被遍历了
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int[] visited = new int[nums.length];
backtrack(res, nums, new ArrayList<Integer>(), visited);
return res;
}
private void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) {
if (tmp.size() == nums.length) {
res.add(new ArrayList<>(tmp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] == 1) continue;
visited[i] = 1;
tmp.add(nums[i]);
backtrack(res, nums, tmp, visited);
visited[i] = 0;
tmp.remove(tmp.size() - 1);
}
}
}