一维DP
划分型:f[] means XXXX ending with i
word break
longest valid parentheses
decode ways
Longest Valid Parentheses
不能算Hard, 但是转移方程需要考虑坐标edge case, bug free不容易
划分型类似Longest Palindromic Substring,word break思路
public int longestValidParentheses(String s) {
if (s == null || s.length() == 0) return 0;
int n = s.length();
int[] f = new int[n];
int max = 0;
for (int i = 1; i < n; i++) {
if (s.charAt(i) == ')') {
if (s.charAt(i - 1) == '(') { //“()”
f[i] = 2 + (i >= 2 ? f[i - 2] : 0);
} else if (i - f[i-1] - 1 >= 0 && s.charAt(i - f[i-1] - 1) == '(') {
f[i] = 2 + f[i-1] + (i - f[i-1] - 2 >= 0 ? f[i - f[i-1] - 2] : 0);
}
}
max = Math.max(max, f[i]);
}
return max;
}
Decode Ways
注意corner case, any valid substring must starts with non-zero
how to handle "0000" ?
state:f[i] means num of decode ways for s.substring(i)
function:
f[i] = isValid(s.substring(i, i + 1)) && f[i + 1] + isValid(s.substring(i, i + 2)) && f[i + 2]
oneDigit != 0
10 <= twoDigits <= 26
res: f[0]
initialize:
f[n] = 0
f[n - 1] = isValid(s.substring(n - 1)) ? 1 : 0
f[n - 2] = isValid(s.substring(n - 2)) ? 1 + f[n - 1] : 0
面试还是写从dfs -> memo的思路更make sense一点
除非面试官要求optimal space complexity-> DP with rolling array
class Solution {
/*
brute force: DFS
decode("226") = decode("26") + isValid("22") && decode("6")
state:f[i] means num of decode ways for s.substring(i)
function:
f[i] = isValid(s.substring(i, i + 1)) && f[i + 1] + isValid(s.substring(i, i + 2)) && f[i + 2]
oneDigit != 0
10 <= twoDigits <= 26
res: f[0]
initialize:
f[n] = 0
f[n - 1] = isValid(s.substring(n - 1)) ? 1 : 0
f[n - 2] = isValid(s.substring(n - 2)) ? 1 + f[n - 1] : 0
O(N) Time and O(N) Space
can use rolling array to optimize space complexity to O(1)
*/
public int numDecodings(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int n = s.length();
int[] f = new int[n + 1];
//initialize
f[n] = 1;
f[n - 1] = s.charAt(n - 1) != '0' ? 1 : 0;
for (int i = n - 2; i >= 0; i--) {
char c = s.charAt(i);
//one digit, need to make sure it's not '0'
if (c != '0') {
f[i] += f[i + 1];
}
int twoDigits = (s.charAt(i) - '0') * 10 + s.charAt(i + 1) - '0';
if (twoDigits >= 10 && twoDigits <= 26) {
f[i] += f[i + 2];
}
}
return f[0];
}
}
Last updated
Was this helpful?