题目点这里
花了好久写的(没有IDE,只能靠println来手动debug了)
不过算法算是码农的基本功,还是需要多多锻炼。
先上代码,肯定不是最优解。
public class Solution {
/*
* @param nums: A list of integers.
* @return: A list of permutations.
*/
public List<List<Integer>> permute(int[] nums) {
// write your code here
Arrays.sort(nums);
int listLength = calListLength(nums.length);
List<List<Integer>> permuteList = new ArrayList<List<Integer>>(listLength);
if(listLength == 0){
permuteList.add(new ArrayList<Integer>());
return permuteList;
}
int returnlength = listLength/nums.length;
int dividenumber = nums.length-1;
boolean flag = false;
if(dividenumber==0){
List<Integer> tmp = new ArrayList<Integer>();
tmp.add(nums[0]);
permuteList.add(tmp);
return permuteList;
}
for(int i = 0;i<listLength;i++){
permuteList.add(new ArrayList<Integer>());
}
while(true){
for(int i = 0;i<listLength/returnlength;i++){
for(int j = 0;j<returnlength;j++){
addNode(permuteList.get(i*returnlength+j),i%(dividenumber+1),nums);
}
}
if(dividenumber==0){
break;
}
returnlength = returnlength/dividenumber;
dividenumber--;
}
return permuteList;
}
public int calListLength(int n){
if(n <= 1){
return n;
}else{
return n*calListLength(n-1);
}
}
public void addNode(List<Integer> list,int n,int[] nums){
int index = 0;
for(int i = 0;i<nums.length;i++){
if(!list.contains(nums[i])){
if(index == n){
list.add(nums[i]);
return;
}else{
index++;
}
}
}
}
}
思路分析:
先分析,一个全排列,总长度应该为源数组长度的阶乘,例如3项全排列应该有6项,4项全排列应该有24项。
而对于每个数而言,出现在全排列中的机会应该是均等的,所以每个数字应该出现(总长度/原数组长度)次。
在给全排列中的每个数组分配第一个数字以后,余下的排列应该是将源数组去掉已经被分配的数字,以这个数组作为源数组,再做一次全排列,直到最后全排列的源数组是一个单一的数字,返回它这是递归的写法。
然而对于递归写法,我不太清楚怎么把最后得到的数字加进结果的数组里。说到底泥腿子码农
所以选择了一条更艰难的路,把递归转为非递归。
思路和递归非常相似,难点在于递归可以简单的把函数堆栈结束的节点放在源数组长度为1的时候,而这里因为没有递归了,所以利用了每次源数组长度下降一的现象,当源数组长度为0时跳出循环。
其实总体思路并不难,一刻钟左右可以想出来,不过调试代码花了很久,两个小时,犯了很多包,如果有IDE的话,情况可能会好点。
网友评论