Skip to content

Commit 464fe6b

Browse files
author
Chris Wu
committed
no message
1 parent dc84873 commit 464fe6b

6 files changed

+217
-0
lines changed

problems/coin-change.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# DP
2+
class Solution(object):
3+
def coinChange(self, coins, amount):
4+
dp = [float('inf')]*(amount+1)
5+
6+
if amount==0: return 0
7+
8+
dp[0] = 0
9+
for coin in coins:
10+
if coin<=amount:
11+
dp[coin] = 1
12+
13+
for a in xrange(amount+1):
14+
for coin in coins:
15+
if a-coin>=0:
16+
dp[a] = min(dp[a], dp[a-coin]+1)
17+
18+
return dp[amount] if dp[amount]!=float('inf') else -1
19+
20+
# BFS
21+
import collections
22+
class Solution(object):
23+
def coinChange(self, coins, amount):
24+
visited = set()
25+
26+
coins.sort(reverse=True)
27+
q = collections.deque([(0, 0)])
28+
29+
while q:
30+
current_amount, count = q.popleft()
31+
32+
if current_amount==amount: return count
33+
if current_amount>amount: continue
34+
if current_amount in visited: continue
35+
visited.add(current_amount)
36+
37+
for coin in coins:
38+
q.append((current_amount+coin, count+1))
39+
return -1

problems/generate-parentheses.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,17 @@ def dfs(path, open_count, open_remain, close_remain):
2020
opt = []
2121
dfs('', 0, N, N)
2222
return opt
23+
24+
25+
class Solution(object):
26+
def generateParenthesis(self, N):
27+
def helper(open_remain, close_remain, s):
28+
if open_remain==0 and close_remain==0:
29+
ans.append(s)
30+
if close_remain>open_remain and close_remain>0:
31+
helper(open_remain, close_remain-1, s+')')
32+
if open_remain>0:
33+
helper(open_remain-1, close_remain, s+'(')
34+
ans = []
35+
helper(N, N, '')
36+
return ans

problems/knight-dialer.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
class Solution(object):
2+
def knightDialer(self, n):
3+
def helper(initial, n):
4+
# return the number of posible count starting from initial with n steps left
5+
6+
if str(initial)+'-'+str(n) in history: return history[str(initial)+'-'+str(n)]
7+
count = 0
8+
9+
if n==0: return 1
10+
for next_number in memo[initial]:
11+
count += helper(next_number, n-1)
12+
13+
history[str(initial)+'-'+str(n)] = count
14+
return count
15+
16+
memo = {
17+
1: [6, 8],
18+
2: [7, 9],
19+
3: [4, 8],
20+
4: [0, 3, 9],
21+
5: [],
22+
6: [0, 1, 7],
23+
7: [2, 6],
24+
8: [1, 3],
25+
9: [2, 4],
26+
0: [4, 6]
27+
}
28+
29+
history = {}
30+
count = 0
31+
32+
for i in xrange(10):
33+
count += helper(i, n-1)
34+
return count % 1000000007
35+
36+
"""
37+
dp[n][i] := number of ways to ends at number i after n moves.
38+
39+
Time: O(N).
40+
Space: O(N). Can reduce to O(1).
41+
"""
42+
class Solution(object):
43+
def knightDialer(self, n):
44+
dp = [[0 for _ in xrange(10)] for _ in xrange(n)]
45+
for i in xrange(10): dp[0][i] = 1 #initialize
46+
47+
memo = {
48+
1: [6, 8],
49+
2: [7, 9],
50+
3: [4, 8],
51+
4: [0, 3, 9],
52+
5: [],
53+
6: [0, 1, 7],
54+
7: [2, 6],
55+
8: [1, 3],
56+
9: [2, 4],
57+
0: [4, 6]
58+
}
59+
60+
for j in xrange(n-1):
61+
for i in xrange(10):
62+
for next_n in memo[i]:
63+
dp[j+1][next_n] += dp[j][i]
64+
65+
return sum(dp[n-1]) % 1000000007
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class Solution(object):
2+
def knightProbability(self, N, K, r, c):
3+
if K==0: return 1
4+
5+
dp = [[[0 for _ in xrange(N)] for _ in xrange(N)] for _ in xrange(K+1)]
6+
7+
dp[0][r][c] = 1
8+
possible = float(0)
9+
10+
for k in xrange(1, K+1):
11+
for i in xrange(N):
12+
for j in xrange(N):
13+
if dp[k-1][i][j]>0:
14+
for x, y in [(i+1, j+2), (i-1, j+2), (i+1, j-2), (i-1, j-2), (i+2, j+1), (i-2, j+1), (i+2, j-1), (i-2, j-1)]:
15+
if 0<=x and x<N and 0<=y and y<N:
16+
dp[k][x][y]+=dp[k-1][i][j]
17+
if k==K: possible+=dp[k-1][i][j] #calculate the possible in the last iteration.
18+
19+
return possible/(8**K)
20+
21+
"""
22+
dp[k][i][j] := number of ways to move to (i, j) after k moves.
23+
dp[k][i][j] = sum(dp[k-1][x][y]), for all possible (x, y) that can moves to (i, j).
24+
25+
Time: O(K*N^2)
26+
Space: O(K*N^2)
27+
"""

problems/largest-1-bordered-square.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
class Solution(object):
2+
def largest1BorderedSquare(self, grid):
3+
if not grid or not grid[0]: return
4+
M, N = len(grid), len(grid[0])
5+
6+
dp = [[[0, 0] for _ in xrange(N+1)] for _ in xrange(M+1)]
7+
ans = 0
8+
for i in xrange(M):
9+
for j in xrange(N):
10+
if grid[i][j]==1:
11+
#[0]
12+
dp[i+1][j+1][0] = dp[i][j+1][0]+1
13+
dp[i+1][j+1][1] = dp[i+1][j][1]+1
14+
15+
#[1]
16+
K = min(dp[i+1][j+1][0], dp[i+1][j+1][1])
17+
18+
#[2]
19+
for k in xrange(K, -1, -1):
20+
if dp[i+1-k+1][j+1][1]>=k and dp[i+1][j+1-k+1][0]>=k:
21+
ans = max(ans, k**2)
22+
break
23+
24+
elif grid[i][j]==0:
25+
#[0]
26+
dp[i+1][j+1][0] = 0
27+
dp[i+1][j+1][1] = 0
28+
29+
return ans
30+
31+
"""
32+
[0]
33+
dp[i+1][j+1][0] := number of the vertical continuous `1`s above grid[i][j]
34+
dp[i+1][j+1][0] := number of the vertical continuous `1`s left to grid[i][j]
35+
36+
For each i and j
37+
Imagine (i, j) is the bottom-right dot of the square.
38+
[1] First, check the max length of the square: K. (through min(number of the vertical continuous `1`s above the bottom-right dot, number of the vertical continuous `1`s left to the bottom-right dot).)
39+
[2] Then, for each possible k, checking from large to small
40+
Get the number of the vertical continuous `1`s above the bottom-left dot.
41+
Get the number of the vertical continuous `1`s left to the top-right dot.
42+
See if they are large enough to form square with border==k.
43+
44+
Time: O(N^3) assume that the N is the length of the grid and grid[0].
45+
Space: O(N^2)
46+
"""

problems/out-of-boundary-paths.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
dp[k][i][j] := number of ways to get to (i, j)
3+
dp[k+1][i][j] = sum(dp[k][x][y]) for all (x, y) that can get to (i, j)
4+
For each k and i and j, also accumulate the ans
5+
6+
Time: O(KMN)
7+
Space: O(KMN)
8+
"""
9+
10+
class Solution(object):
11+
def findPaths(self, M, N, K, i, j):
12+
ans = 0
13+
14+
dp = [[[0 for _ in xrange(N)] for _ in xrange(M)] for _ in xrange(K+1)]
15+
dp[0][i][j] = 1
16+
17+
for k in xrange(K):
18+
for i in xrange(M):
19+
for j in xrange(N):
20+
if dp[k][i][j]>0:
21+
for x, y in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]:
22+
if x<0 or x>=M or y<0 or y>=N:
23+
ans+=dp[k][i][j]
24+
else:
25+
dp[k+1][x][y]+=dp[k][i][j]
26+
return ans % (1000000007)

0 commit comments

Comments
 (0)