Problem 3 Permutation I母题
Method 1 (只对combination有效)不能不加,只能加,一个一个加
High Level
什么是一个解?一个permutation
如何构造一个解?
每一层:加一个元素进来
分支:这一层所有可以加的元素中,你加谁呀?
在哪收集解(对比subset):所有元素都contains进来才行
注意
All Path problem里,我们不允许同一个node在同一个path上使用多次,但是我们允许同一个node在不同path上使用多次
Q我怎么知道我加这个元素没有?
Implement 1
TC& SC: O(n! * n), O(n)
public List<List<Integer>> permutation(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if (nums == null || nums.length == 0) {
return result;
}
List<Integer> current = new ArrayList<>();
backTracking(result, nums, current, 0);
return result;
}
// index:当前层我要固定的位置是谁:层数的信息
private void backTracking(List<List<Integer>> result, int[] nums, List<Integer> current, int index) {
if (index == nums.length) {
result.add(new ArrayList<>(current));
return;
}
for (int i = 0; i < nums.length; i++) {
// method 1: O(n) time to check current 里面是不是有nums[i], list: contains(val), O(n)
if (!current.contains(nums[i])) {
current.add(nums[i]);
backTracking(result, nums, current, index + 1);
current.remove(current.size() - 1);
}
}
}
Implement 2
Use Case:
我想知道某一个Character我在之前加过没加过==> loop up operation ==> set
Set<Integer> elementAddedSoFarInPreviousLevel
注意,这是对不同层之间纵向的去重,所以应该在不同层之间传递,一定是在主函数创建
这个代码可以跑过所有的test case,但是稳挂,因为这个没办法对付去重??
public List<List<Integer>> permutation(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if (nums == null || nums.length == 0) {
return result;
}
Set<Character> elementAddedSoFar = new HashSet<>();
List<Integer> current = new ArrayList<>();
backTracking(result, nums, current, 0, elementAddedSoFar);
return result;
}
// index:当前层我要固定的位置是谁:层数的信息
private void backTracking(List<List<Integer>> result, int[] nums, List<List<Integer>> current, int index, Set<Character> elementAddedSoFar) {
if (index == nums.length) {
result.add(new ArrayList<>(current));
return;
}
for (int i = 0; i < nums.length; i++) {
// method 2: O(n) space to check if previous level already used this character
if (!elementAddedSoFar.contains(nums[i])) {
elementAddSoFar.add(nums[i]);
current.add(nums[i]);
backTracking(result, nums, current, index + 1, elementAddSoFar);
elementAddSoFar.remove(nums[i]);
current.remove(current.size() - 1);
}
}
}
不同层之间的重复是 同一条path 同样index上的元素不能用多次 vs
同样value的元素不能用多次这道题之所以能过是因为这道题没有重复所有才能过,但是意义是不对的,要是有重复元素就错了
public List<List<Integer>> permutation(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if (nums == null || nums.length == 0) {
return result;
}
//注意这里!!!!!!!!!不是element,而是用index
Set<Character> indexAddedSoFar = new HashSet<>();
List<Integer> current = new ArrayList<>();
backTracking(result, nums, current, 0, indexAddedSoFar);
return result;
}
// index:当前层我要固定的位置是谁:层数的信息
private void backTracking(List<List<Integer>> result, int[] nums, List<List<Integer>> current, int index, Set<Character> indexAddedSoFar) {
if (index == nums.length) {
result.add(new ArrayList<>(current));
return;
}
for (int i = 0; i < nums.length; i++) {
// method 2: O(n) space to check if previous level already used this character
if (!indexAddedSoFar.contains(i)) {
indexAddedSoFar.add(i);
current.add(nums[i]);
backTracking(result, nums, current, index + 1, indexAddedSoFar);
indexAddedSoFar.remove(i);
current.remove(current.size() - 1);
}
}
}
Method 2 swap swap
既不需要O(n)的时间,也不需要O(n)的空间
High Level 保持不变:通过swap-swap的方式来固定一个元素
利用区间O(1)知道哪些元素不能用,哪些元素还没用过可以固定过来
[0, index - 1)固定好的元素
[index, nums.length - 1] 还没背固定过的,可以用来被固定过来的元素
List Version
public List<List<Integer>> permutation(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if (nums == null || nums.length == 0) {
return result;
}
backTracking(result, nums, 0);
return result;
}
// level: index: 当前层我正要固定那个index
// [0, index - 1]已经固定好的元素 不能用
// [index, nums.length - 1]可以用来被固定到当前位置的元素
private void backTracking(List<List<Integer> result, int[] nums, int level) {
if(index == nums.length) {
List<Integer> current = new ArrayList<>();
for (int num: nums) {
current.add(num);
}
result.add(current);
return;
}
for (int i = level; i < nums.length; i++) {
swap(nums, i , level);
backTracking(result, nums, level + 1);
swap(nums, i, level);
}
}
private void swap(int[] nums, int i , int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
String Version
public class Solution {
public List<String> permutations(String input) {
// initial the return
List<String> ret = new ArrayList<String>();
// transfer input to a curChar
char[] curChar = input.toCharArray();
// curLevel: the String position
dfsHelper(0, ret, curChar);
return ret;
}
// dfsHelper(curLevel, ret, curChar)
// corner case
//if curLevel reaches the curChar length
// ret.add(curChar change to the )
// return
// iterate the possible position: from curLevel to the curChar.length
// swap (possiblePostion, curLevel, curChar)
// dfsHelper(curLevel, ret, curChar)
// swap (possiblePostion, curLevel, curChar)
private void dfsHelper(int curLevel, List<String> ret, char[] curChar) {
if (curLevel == curChar.length) {
ret.add(new String(curChar));
return;
}
for (int possiblePosition = curLevel; possiblePosition < curChar.length; possiblePosition++) {
swap(possiblePosition, curLevel, curChar);
dfsHelper(curLevel + 1, ret , curChar);
swap(curLevel, possiblePosition, curChar);
}
}
private void swap(int a, int b, char[] curChar) {
char temp = curChar[a];
curChar[a] = curChar[b];
curChar[b] = temp;
}
}
// TC O(n!)
// SC O(n)
Last updated