Skip to content

Commit af34a98

Browse files
committed
Add dynamic programming
1 parent b8a9643 commit af34a98

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Solution:
2+
def longestSubarray(self, nums: List[int]) -> int:
3+
"""
4+
This problem essentially asks the longest contiguous subarray with the maximum value
5+
Note we can't use two-pointer sliding window because we cannot undo bitwise AND
6+
"""
7+
longest = 0
8+
current_len = 0
9+
max_val = 0 # min value in nums is 1, so set max_val to zero
10+
11+
for num in nums:
12+
if num > max_val: # meet higher value, restart counting from current element
13+
max_val = num
14+
current_len = 1
15+
longest = 1
16+
17+
elif num == max_val:
18+
current_len += 1
19+
else:
20+
current_len = 0 # if not set to zero when meeting smaller element, the case nums = [5,5,3,5] will fail
21+
# because we continue counting the third 5 as consecutive with prior two 5s even there's a lower value 3 that interrupts
22+
# the array
23+
24+
longest = max(longest, current_len)
25+
return longest
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# https://leetcode.com/problems/valid-number/solutions/23728/a-simple-solution-in-python-based-on-dfa/
2+
# define an NFA
3+
class Solution():
4+
def isMatch(self, s: str, p: str) -> bool:
5+
"""
6+
1, If p.charAt(j) == s.charAt(i) : dp[i][j] = dp[i-1][j-1]; s[i] matches p[j], remove both p[j] AND s[i]
7+
2, If p[j] == '.' : dp[i][j] = dp[i-1][j-1]; Same as above, '.' Matches any single character in s, s[i] matches p[j] == '.', remove both p[j] == '.' AND s[i]
8+
3, If p.charAt(j) == '*': '*' matches any number of previous character p[j-1] in s
9+
here are two sub conditions:
10+
1 if p[j-1] != s[i] : dp[i][j] = dp[i][j-2] // p[j-1] cannot match s[i], "*" can only counts as empty for best match, remove p[j] == '*' and p[j-1], but don't remove anything from s, so p[j-2] will be compared to s[i] for match
11+
2 if p[j-1] == s[i] or p[j-1] == '.':
12+
dp[i][j] = dp[i-1][j] // in this case, * counts as multiple s[i-1], only consume s: consume s[i], but don't consume p so that "p[j-1]*" will still be used to compare to s[i-1], s[i-2], ...
13+
or dp[i][j] = dp[i][j-1] // in this case, * counts as single, only consume p: remove p[j] == '*' so that p[j-1] will be compared to s[i] for exact match
14+
or dp[i][j] = dp[i][j-2] // in this case, * counts as empty, only consume p: remove p[j] == '*' and p[j-1], but don't remove anything from s, so p[j-2] will be compared to s[i] for match
15+
"""
16+
m, n = len(s), len(p)
17+
dp = [[0] * (n+1) for _ in range(m+1)] # whether s[:i+1] matches p[:j+1] (first i characters from s matches first j characters from p)
18+
dp[0][0] = True # empty string always match
19+
20+
for j in range(n):
21+
if p[j] == '*' and dp[0][j-1]:
22+
dp[0][j+1] = True
23+
24+
# we're setting let i_prime = i+1, j_prime = j+1, each iteration we're setting dp[i_prime][j_prime]
25+
for i in range(m):
26+
for j in range(n):
27+
if p[j] == '.' or p[j] == s[i]:
28+
dp[i+1][j+1] = dp[i][j]
29+
if p[j] == '*': # considering "p[j-1]*"
30+
if p[j-1] != s[i] and p[j-1] != '.': # "p[j-1]*" doesn't match anything in s[i], s[i-1]..., therefore we have to remove it entirely (treat as empty string)
31+
dp[i+1][j+1] = dp[i+1][j-1]
32+
else: # if p[j-1] == s[i] or p[j-1] == '.': "p[j-1]*" could match zero, one, or multiple characters that ends at s[i]
33+
dp[i+1][j+1] = dp[i+1][j] or dp[i][j+1] or dp[i+1][j-1]
34+
return dp[m][n]

0 commit comments

Comments
 (0)