質問の詳細
繰り返し番号のないシーケンスが与えられた場合、可能なすべての順列を返します。
例:
入力:[1,2,3]
出力:
[
[1,2,3
]、
[1,3,2]、
[2,1,3]、
[2,3,1 ]、[3,1,2 ]、
[3,2,1]
]
この質問は、比較的単純で古典的なバックトラッキングの質問、または順列と組み合わせの完全なリストです。この種の質問は、バックトラック(dfs + delete操作)によって完了することができます。この記事を書く目的は、バックトラッキングの一般的な記述を記録することです。 。、2つ目は、javaでの参照に注意を払う必要があることを思い出してください。
トピック分析
バックトラッキング問題の一般的な考え方は次のとおりです。
def backtrack(路径,选择列表):
if满足条件:
添加到最终结果
return
for 选择 in 选择列表:
做选择
backtrack(路径,选择列表)
撤销选择
(これはLeetCodeのコメント領域で私が思うこと
です。@ Teki、それは良いことだと思います)コードを書くのは基本的にこの考えです。
ここで書いたコードは少し冗長です。実際、配列をマークせずにListのcontainsメソッドを直接使用できます(ここにマークを付けて、将来これを使用します)。通常、Javaはまだ少しだけ使用されているため、さびています。 。
コードを貼り付けます:
//有思路了,就是建立一个marked数组,记录标记情况,然后for循环,跳过标记的,然后一直往下搜索就行如
//可以判断一下数组的和是否等于长度来判断是否完了
//总体还是很简单的
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> results = new LinkedList<>();
if(nums==null||nums.length==0)
return results;
for(int i=0;i<nums.length;i++)
{
int[] marked = new int[nums.length];
backtrack(nums,i,marked,new LinkedList<Integer>(),results,0);
}
return results;
}
public void backtrack(int[] nums, int index, int[] marked, LinkedList<Integer> result, List<List<Integer>> results,int count){
//count用于判断当前是否满了
if(count==nums.length-1&&marked[index]==0){
result.add(nums[index]);
// System.out.println(result);
results.add((List<Integer>)result.clone());//这里需要进行一个拷贝,不然里面存的都是一个变量,最后值都为0了
result.remove(result.size()-1);
return;
}
//判断当前索引是否被遍历过
if(marked[index]==1)
return;
//如果都没有,则说明可以遍历
//先把自己放进result中去
result.add(nums[index]);
marked[index]=1;
count++;
//再从头开始遍历
for(int j=0;j<nums.length;j++)
backtrack(nums,j,marked,result,results,count);
//最终把自己删掉
// System.out.println(nums[index]);
result.remove(result.size()-1);
marked[index]=0;
count--;
}
ここで、results.add((List<Integer>)result.clone());
この行で最初に書いたのは、results.add(result)
(バックトラックのために)最終的な出力結果がすべて空であるということでした。しばらく考えた後、これは基本型ではなく参照型であることを思い出しました。 、それを実行する必要があります一度コピーした後、リストのクローンを作成できないことがわかりました。しばらくチェックしたところ、LinkedListまたはArrayListしか使用できないことがわかり、強制的な型変換が必要でした。