Skip to content

Commit

Permalink
fix 047 py, backtrack cheatsheet
Browse files Browse the repository at this point in the history
  • Loading branch information
yennanliu committed Oct 11, 2023
1 parent 5684bcb commit cc87559
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 52 deletions.
118 changes: 68 additions & 50 deletions doc/cheatsheet/backtrack.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

## 0) Concept

### 0-1) Types

- 3 things to consider :
- `Route` : The choices have made
- `Choice list` : The choices we can select currently
Expand All @@ -31,6 +29,8 @@
- set
- array

### 0-1) Types

- Problems types

- Type 1) : `Subsets` (子集)
Expand Down Expand Up @@ -139,10 +139,11 @@
_cnt[nums[i]] += 1
```

- Type 2) : `Permutations (排列組合)`
- LC 46
- Type 2) : `Permutations (排列組合)` (全排列)
- Problems : LC 46, 47
- (for loop call help func) + contains + pop(-1)
- backtrack. via `contains` remove already used numbers and return all cases
- contains (visited) (or not in `cur`) + for loop + pop(-1) + help func
- NO NEED to use start_idx
```python
# ...
res = []
Expand All @@ -161,56 +162,73 @@
cur.pop(-1)
# ...
```
```java
// java
// https://leetcode.com/problems/subsets/solutions/27281/a-general-approach-to-backtracking-questions-in-java-subsets-permutations-combination-sum-palindrome-partitioning/
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
// Arrays.sort(nums); // not necessary
backtrack(list, new ArrayList<>(), nums);
return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(tempList));
} else{
for(int i = 0; i < nums.length; i++){
if(tempList.contains(nums[i])) continue; // element already exists, skip
tempList.add(nums[i]);
backtrack(list, tempList, nums);
tempList.remove(tempList.size() - 1);
}
}
}
- Permutations I (排列組合)
- LC 46
```python
# python
class Solution(object):
def permute(self, nums):
def help(cur):
if len(cur) == n_len:
if cur not in res:
res.append(list(cur))
return
if len(cur) > n_len:
return
for i in nums:
#print ("i = " + str(i) + " cur = " + str(cur))
if i not in cur:
cur.append(i)
help(cur)
"""
NOTE !!! : we UNDO the last op we just made (pop last element we put into array)
"""
cur.pop(-1)
# edge case
if not nums:
return [[]]
n_len = len(nums)
res = []
help([])
#print ("res = " + str(res))
return res
```

- `Permutations II (排列組合)`
- LC 47
```java
// java
// https://leetcode.com/problems/subsets/solutions/27281/a-general-approach-to-backtracking-questions-in-java-subsets-permutations-combination-sum-palindrome-partitioning/
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, new boolean[nums.length]);
return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, boolean [] used){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(tempList));
} else{
for(int i = 0; i < nums.length; i++){
if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue;
used[i] = true;
tempList.add(nums[i]);
backtrack(list, tempList, nums, used);
used[i] = false;
tempList.remove(tempList.size() - 1);
}
}
}
```python
# python
class Solution(object):
def permuteUnique(self, nums):
def help(res, cur, cnt):
if len(cur) == len(nums):
if cur not in res:
res.append(cur[:])
return
if len(cur) > len(nums):
return
for x in _cnt:
#print ("i = " + str(i) + " cur = " + str(cur))
#if i not in cur:
if _cnt[x] > 0:
cur.append(x)
_cnt[x] -= 1
help(res, cur, _cnt)
"""
NOTE !!! : we UNDO the last op we just made (pop last element we put into array)
"""
cur.pop(-1)
_cnt[x] += 1
# edge case
if not nums:
return [[]]
_cnt = Counter(nums)
#print ("_cnt = " + str(_cnt))
res = []
cur = []
help(res, cur, _cnt)
return res
```

- Type 3) : `Combinations (組成)`
Expand Down
129 changes: 127 additions & 2 deletions leetcode_python/Backtracking/permutations-ii.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,131 @@
# V0
"""
# V1
47. Permutations II
Medium
8.1K
137
Companies
Given a collection of numbers, nums, that might contain duplicates, return all possible unique permutations in any order.
Example 1:
Input: nums = [1,1,2]
Output:
[[1,1,2],
[1,2,1],
[2,1,1]]
Example 2:
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
Constraints:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
"""

# V0
# IDEA : BACKTRACK + LC 46 + COUNTER
# https://leetcode.com/problems/permutations-ii/editorial/
class Solution(object):
def permuteUnique(self, nums):
def help(res, cur, cnt):
if len(cur) == len(nums):
if cur not in res:
res.append(cur[:])
return
if len(cur) > len(nums):
return
for x in _cnt:
#print ("i = " + str(i) + " cur = " + str(cur))
#if i not in cur:
if _cnt[x] > 0:
cur.append(x)
_cnt[x] -= 1
help(res, cur, _cnt)
"""
NOTE !!! : we UNDO the last op we just made (pop last element we put into array)
"""
cur.pop(-1)
_cnt[x] += 1
# edge case
if not nums:
return [[]]
_cnt = Counter(nums)
#print ("_cnt = " + str(_cnt))
res = []
cur = []
help(res, cur, _cnt)
return res

# V0'
# IDEA : BACKTRACK + LC 46 -> TLE
class Solution(object):
def permuteUnique(self, nums):
def help(res, cur, cnt):
if len(cur) == len(nums):
if cur not in res:
res.append(cur[:])
return
if len(cur) > len(nums):
return
for i in range(len(nums)):
#print ("i = " + str(i) + " cur = " + str(cur))
#if i not in cur:
if _cnt[nums[i]] > 0:
cur.append(nums[i])
_cnt[nums[i]] -= 1
help(res, cur, _cnt)
"""
NOTE !!! : we UNDO the last op we just made (pop last element we put into array)
"""
cur.pop(-1)
_cnt[nums[i]] += 1
# edge case
if not nums:
return [[]]
_cnt = Counter(nums)
print ("_cnt = " + str(_cnt))
res = []
cur = []
help(res, cur, _cnt)
#print ("res = " + str(res))
return res

# V1
# IDEA : BACKTRACK + COUNTER
# https://leetcode.com/problems/permutations-ii/editorial/
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
results = []
def backtrack(comb, counter):
if len(comb) == len(nums):
# make a deep copy of the resulting permutation,
# since the permutation would be backtracked later.
results.append(list(comb))
return

for num in counter:
if counter[num] > 0:
# add this number into the current combination
comb.append(num)
counter[num] -= 1
# continue the exploration
backtrack(comb, counter)
# revert the choice for the next exploration
comb.pop()
counter[num] += 1

backtrack([], Counter(nums))

return results

# V2
# https://blog.csdn.net/weixin_38111819/article/details/79131409
# https://blog.csdn.net/XX_123_1_RJ/article/details/81021815
# IDEA : DFS
Expand Down

0 comments on commit cc87559

Please sign in to comment.