Skip to content

Commit a263b6a

Browse files
author
Yan Cao
committed
Updated DFS questions. Added tree helper
1 parent 1cca773 commit a263b6a

14 files changed

+171
-88
lines changed

Interviews/BFS_DFS.py

+2-33
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@
88
* Postorder(Recursive, Iterative)
99
"""
1010

11-
class TreeNode:
12-
def __init__(self, x):
13-
self.val = x
14-
self.left = None
15-
self.right = None
11+
from Tree_Helper.tree_helper import *
1612

1713
def BFS_level_order_traversal(root):
1814
if not root:
@@ -144,23 +140,6 @@ def DFS_postorder(root):
144140
return result
145141

146142

147-
def create_bst_from_array(A, start=None, end=None):
148-
if start is None and end is None:
149-
start = 0
150-
end = len(A) - 1
151-
152-
if start > end:
153-
return None
154-
155-
mid = (start + end) / 2
156-
root = TreeNode(A[mid])
157-
158-
root.left = create_bst_from_array(A, start, mid - 1)
159-
root.right = create_bst_from_array(A, mid + 1, end)
160-
161-
return root
162-
163-
164143
A = [ i for i in range(10) ]
165144
new_tree = create_bst_from_array(A)
166145
"""
@@ -248,15 +227,5 @@ def preorder_doubly_flatten(root):
248227
249228
print BFS_level_order_traversal(new_tree)
250229
251-
def print_tree(head):
252-
while head:
253-
print head.val,
254-
if head.left:
255-
print 'left', head.left.val,
256-
if head.right:
257-
print 'right', head.right.val,
258-
print ''
259-
head = head.right
260-
261-
print_tree(head)
230+
print_tree_as_list(head)
262231
"""
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
#####From [blog](http://blog.csdn.net/luckyxiaoqiang/article/details/7518888#topic6)
3+
4+
Not sure if this is usefull but the code seems pretty important
5+
"""
6+
7+
def get_kth_level_nodes(root, k):
8+
if not root:
9+
return 0
10+
if k == 1:
11+
return k
12+
13+
left_count = get_kth_level_nodes(root.left, k-1)
14+
right_count = get_kth_level_nodes(root.right, k-1)
15+
16+
return left_count + right_count
17+
18+
"""
19+
from Tree_Helper.tree_helper import *
20+
A = [ i for i in range(20)]
21+
root = create_bst_from_array(A)
22+
23+
DFS_level_order_traversal(root)
24+
25+
print get_kth_level_nodes(root, 5)
26+
"""
File renamed without changes.

Interviews/Coin_Change.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
#####From [Geeksforgeeks](http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/)
3+
4+
Similar to CC150, just allow coin with 1, 3, 5 right now
5+
6+
Several ways to ask
7+
1. How many ways?
8+
2. What are the ways?
9+
3. Minimum coin number?
10+
"""
11+
12+
# This is same to Combination Sum I
13+
def coin_change(value):
14+
res = [0, 0, 0] # [num_5, num_3, num_1]
15+
ret = []
16+
coin_change_helper(value, res, ret, 0)
17+
return ret
18+
19+
def coin_change_helper(value, res, ret, cur_face_value):
20+
if value == 0:
21+
ret.append(res[:])
22+
if value <= 0:
23+
return
24+
for i in range(cur_face_value, 3):
25+
res[i] += 1
26+
coin_change_helper(value - [5, 3, 1][i], res, ret, i)
27+
res[i] -= 1
28+
29+
print coin_change(5)

Interviews/Tree_Helper/__init__.py

Whitespace-only changes.

Interviews/Tree_Helper/tree_helper.py

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python
2+
3+
class TreeNode:
4+
def __init__(self, x):
5+
self.val = x
6+
self.left = None
7+
self.right = None
8+
9+
def DFS_level_order_traversal(root):
10+
ret = {}
11+
DFS_helper(ret, 1, root)
12+
for level in sorted(ret.keys()):
13+
print ret[level]
14+
15+
def DFS_helper(ret, level, root):
16+
if not root:
17+
return
18+
19+
ret.setdefault(level, []).append(root.val)
20+
DFS_helper(ret, level + 1, root.left)
21+
DFS_helper(ret, level + 1, root.right)
22+
23+
def create_bst_from_array(A, start=None, end=None):
24+
if start is None and end is None:
25+
start = 0
26+
end = len(A) - 1
27+
28+
if start > end:
29+
return None
30+
31+
mid = (start + end) / 2
32+
root = TreeNode(A[mid])
33+
34+
root.left = create_bst_from_array(A, start, mid - 1)
35+
root.right = create_bst_from_array(A, mid + 1, end)
36+
37+
return root
38+
39+
def print_tree_as_list(head):
40+
while head:
41+
print head.val,
42+
if head.left:
43+
print 'left', head.left.val,
44+
if head.right:
45+
print 'right', head.right.val,
46+
print ''
47+
head = head.right

Leetcode/Combination_Sum.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ def combinationSum_helper(self, candidates, target, res, ret):
2727
ret.append(res[:])
2828
return
2929
for i, num in enumerate(candidates):
30-
if target >= num:
31-
res.append(num)
32-
self.combinationSum_helper(candidates[i:], target - num, res, ret)
33-
res.pop()
30+
if target - num < 0:
31+
continue
32+
res.append(num)
33+
self.combinationSum_helper(candidates[i:], target - num, res, ret)
34+
res.pop()
3435

35-
# Improvements: only continue when target > num ,else stop
36+
# Continue when target < num

Leetcode/Combination_Sum_II.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def combinationSum_helper(self, candidates, target, res, ret):
2929
ret.append(res[:])
3030
return
3131
for i, num in enumerate(candidates):
32-
if target < num or (i > 0 and num == candidates[i-1]):
32+
if target < num or (i > 0 and candidates[i] == candidates[i-1]):
3333
continue
3434
res.append(num)
3535
self.combinationSum_helper(candidates[i+1:], target - num, res, ret)

Leetcode/Permutations.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ def permute(self, num):
1414

1515
def permute_1(self, num):
1616
ret = []
17-
self.permute_helper([], num, ret)
17+
self.permute_helper(num, [], ret)
1818
return ret
1919

20-
def permute_helper(self, res, num, ret):
20+
def permute_helper(self, num, res, ret):
2121
if len(num) == 0:
2222
ret.append(res[:])
2323
return
2424

2525
for i, n in enumerate(num):
2626
res.append(n)
27-
self.permute_helper(res, num[:i] + num[i+1:], ret)
27+
self.permute_helper(num[:i] + num[i+1:], res, ret)
2828
res.pop()
2929

3030
# Do this "inplace"

Leetcode/Permutations_II.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def permuteUnique_helper(self, num, res, ret):
2222
ret.append(res[:])
2323
return
2424
for i, n in enumerate(num):
25-
if i > 0 and n == num[i-1]:
25+
if i > 0 and num[i] == num[i-1]:
2626
continue
2727
res.append(n)
2828
self.permuteUnique_helper(num[:i] + num[i+1:], res, ret)

Leetcode/Subsets.py

+16-18
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,22 @@ class Solution:
2323
# @param S, a list of integer
2424
# @return a list of lists of integer
2525
def subsets(self, S):
26-
return self.subsets_1(S)
26+
return self.subsets_2(S)
27+
28+
# Recursion method
29+
def subsets_2(self, S):
30+
ret = []
31+
self.subsets_helper(sorted(S), [], ret)
32+
return ret
33+
34+
def subsets_helper(self, S, res, ret):
35+
ret.append(res[:])
36+
37+
for i, el in enumerate(S):
38+
res.append(el)
39+
self.subsets_helper(S[i+1:], res, ret)
40+
res.pop()
41+
# Keep in mind the sorted
2742

2843
# Iteration method
2944
def subsets_1(self, S):
@@ -36,20 +51,3 @@ def subsets_1(self, S):
3651
res.append(el[:])
3752
ret = res[:]
3853
return ret
39-
40-
# Recursion method
41-
def subsets_2(self, S):
42-
ret = []
43-
self.subsets_helper(0, sorted(S), [], ret)
44-
return ret
45-
46-
def subsets_helper(self, i, S, res, ret):
47-
if i == len(S):
48-
ret.append(res[:])
49-
return
50-
self.subsets_helper(i+1, S, res, ret) # No element i
51-
res.append(S[i])
52-
self.subsets_helper(i+1, S, res, ret) # With element i
53-
res.pop()
54-
55-
# Keep in mind the sorted

Leetcode/Subsets_II.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ def subsetsWithDup_1(self, S):
3939
# Recursion way
4040
def subsetsWithDup_2(self, S):
4141
ret = []
42-
self.subsetsWithDup_rec(0, sorted(S), [], ret)
42+
self.subsetsWithDup_rec(sorted(S), [], ret)
4343
return ret
4444

45-
def subsetsWithDup_rec(self, i, S, res, ret):
46-
if i == len(S):
47-
ret.append(res[:])
48-
return
49-
if len(res)==0 or S[i] != res[-1]: # This is tricky, but I should be careful, it's checking against
50-
self.subsetsWithDup_rec(i+1, S, res, ret) # last res char, but not S[i-1]
51-
res.append(S[i])
52-
self.subsetsWithDup_rec(i+1, S, res, ret)
53-
res.pop()
45+
def subsetsWithDup_rec(self, S, res, ret):
46+
ret.append(res[:])
47+
48+
for i, el in enumerate(S):
49+
if i > 0 and S[i] == S[i-1]:
50+
continue
51+
res.append(el)
52+
subsetsWithDup_rec(S[i+1:], res, ret)
53+
res.pop()

coding_index.md

+27-14
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* [x] Combination Sum
1313
* [x] Combination Sum II
1414
* [x] Letter Combination of a Phone Number
15-
* [ ] 找零钱
15+
* [x] 找零钱 == Combination Sum I
1616

1717
-----
1818

@@ -21,19 +21,32 @@
2121

2222
-----
2323

24-
######Note:
25-
做Permutation, Combination和Subset的感觉非常像,注意
26-
27-
1. 结束条件都是用完所有可用的char, 也就是i == len(n). 然后在ret.append(res[:]), 这里千万别忘了要return cancel函数
28-
2. 做for循环的时recursion函数的输入会有差别(记得这里用enumerate会方便好多)
29-
1. Permutation传入剩余num_list 是 num[:i] + num[i+1], 因为只是除去当前数字, permute剩余
30-
2. Combination传入剩余num_list 是 num[i+1:], 因为除去比当前数字之前的数, combine剩余
31-
3. Subsets其实也应该是S[i+1:],除去之前可能的set. 但是与前两者不同的是循环的内容不同, Subset只有存在和不存在两种情况,所以等于是loop一个恒为2的循环,而第一种情况还有特殊条件,这个一定要仔细看好。
32-
4. Permutation&Combination两者相同的地方都是
33-
1. res.append(n)
34-
2. do combine_rec/permute_rec
35-
3. res.pop()
36-
3. 仔细观察这三道题就会发现, 其实I都是输入没有重复, 而II都是输入有重复,但输出不能有重复的题目.
24+
#####总结
25+
Permutations II,
26+
Combinations,
27+
Combinations Sum II
28+
和Subset II都是DFS, 区别在于
29+
1.```res```放入```ret```的条件不一样
30+
* Permu - ```len(res) = len(S)```
31+
* Combin - ```len(res) == k```
32+
* Combin Sum - ```target == 0```
33+
* Subsets - 只要生成新的res就要存一次
34+
前三种题存过结果只后程序应该return
35+
2. 循环内call recursion时的输入变量不一样
36+
* Permu - ```permu_helper(num[:i] + num[i+i:], res, ret)```(除了S[i])
37+
* Combin - ```comb_helper(i+1, n, k, res, ret)```(S[i+1:])
38+
* Combin Sum - ```comb_sum_helper(num[i:], target - n, res, ret)```(S[i:])
39+
* Subsets - ```sub_helper(S[i+1:], res, ret)```(S[i+1:])
40+
S[i+1:]决定了res内是不会有重复项的(除非S本身就有重复), S[i:]让当前元素可以重复使用
41+
* II类去重题相比较I类题唯一的差别就是在循环的第一行需要check```if i > 0 and S[i] == S[i-1]: continue```
42+
* 注意II类题都需要先```sort```, 因为去重是判断前项相等否
43+
* 普通题目看情况如果要求输入时```res```内的元素有序那也需要```sort```
44+
* Comb Sum题有一点点特殊在于在循环内需要判断```target - num < 0: continue```
45+
* Comb Sum II和I比题目有点点变化在于,数字不能无限重取,只能有限重取,
46+
所以是```comb_sum_II_helper(num[i+1:], target - n, res, ret)```
47+
* 记得尽量用```enumerate```
48+
49+
复杂度O(n)??
3750

3851
-----
3952

run.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#!/usr/bin/env python
22

3-
file_name = 'Count_and_Say'
4-
func_name = 'countAndSay'
3+
file_name = 'Subsets'
4+
func_name = 'subsets'
55

66
import importlib
77
module = importlib.import_module('Leetcode.%s' % file_name)
88
instance = module.Solution()
99

10-
print getattr(instance, func_name)(6)
10+
print getattr(instance, func_name)([1,2,3])

0 commit comments

Comments
 (0)