동적 프로그래밍
예
5. 가장 긴 회문 부분 문자열
https://leetcode-cn.com/problems/longest-palindromic-substring/
다중 조건 동적 프로그래밍, 다중 조건 채우기 양식
class Solution {
public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
// 有一个字符串为空串
if (n * m == 0) {
return n + m;
}
// DP 数组
int[][] D = new int[n + 1][m + 1];
// 边界状态初始化,需要这么多操作才能完成转换过程
for (int i = 0; i < n + 1; i++) {
D[i][0] = i;
}
for (int j = 0; j < m + 1; j++) {
D[0][j] = j;
}
// 计算所有 DP 值
for (int i = 1; i < n + 1; i++) {
for (int j = 1; j < m + 1; j++) {
int left = D[i - 1][j] + 1;
int down = D[i][j - 1] + 1;
int left_down = D[i - 1][j - 1];
if (word1.charAt(i - 1) != word2.charAt(j - 1)) {
left_down += 1;
}
D[i][j] = Math.min(left, Math.min(down, left_down));
}
}
return D[n][m];
}
}
다른 이진 검색 트리
https://leetcode-cn.com/problems/unique-binary-search-trees/solution/bu-tong-de-er-cha-sou-suo-shu-by-leetcode-solution/은
실제로 유도 공식입니다. 동적 프로그래밍의 상태 전이 방정식 얻기
class Solution {
public int numTrees(int n) {
int[] G = new int[n + 1];
G[0] = 1;
G[1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
G[i] += G[j - 1] * G[i - j];
}
}
return G[n];
}
}
139. 단어 분할
https://leetcode-cn.com/problems/word-break/1
차원 순회 형태의 동적 프로그래밍 :
public class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
Set<String> wordDictSet = new HashSet(wordDict);
boolean[] dp = new boolean[s.length() + 1];
dp[0] = true;
for (int i = 1; i <= s.length(); i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && wordDictSet.contains(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
}
53. 최대 하위 시퀀스 합계
1 차원 동적 프로그래밍
class Solution {
public int maxSubArray(int[] nums) {
int pre = 0, maxAns = nums[0];
for (int x : nums) {
pre = Math.max(pre + x, x);
maxAns = Math.max(maxAns, pre);
}
return maxAns;
}
}
https://leetcode-cn.com/problems/maximum-subarray/solution/zui-da-zi-xu-he-by-leetcode-solution/
64. 최소 경로 및
https://leetcode-cn.com/problems/minimum-path-sum/
동적 프로그래밍 솔루션 :
초기화 : 첫
번째 열과 첫 번째 행은 고정되어 있으며 이전 또는 왼쪽의 요소에서만 올 수 있습니다.
dp 방정식 :
다음 dp [i] [j]는 왼쪽 또는 위쪽의 두 방향에서 올 수 있습니다 (경로의 방향은 아래쪽 또는 오른쪽 만 가능).
요약하면 상태 전이 방정식 :
dfs 솔루션 :
https://leetcode-cn.com/problems/minimum-path-sum/solution/dfs-ji-yi-ji-hu-100-by-piaohao/
상향식 솔루션, 메모리 추가 필요
class Solution {
private int M;
private int N;
private int[][] memo;
//dfs + 记忆
public int minPathSum(int[][] grid) {
M = grid.length;
N = grid[0].length;
memo = new int[M][N];
for (int i = 0; i < M; i++) {
Arrays.fill(memo[i], -1);
}
return dfs(grid, 0, 0);
}
private int dfs(int[][] grid, int r, int c) {
//fail,若越界,则认为不可达,距离为无穷大
if (r < 0 || r >= M || c < 0 || c >= N) return Integer.MAX_VALUE;
if (memo[r][c] > -1) return memo[r][c]; // 只要有就返回
//若到达终点,终点的贡献值是其本身
if (r == M - 1 && c== N - 1) return grid[M - 1][N - 1];
//右边的点到终点最短的路径,决策1:从右边走
int right = dfs(grid, r, c + 1);
//下面的点到终点的最短路径,决策2:从下边走
int down = dfs(grid, r + 1, c);
//取两者的较小值,计算出当前点的最小路径值
int ans = Math.min(right, down) + grid[r][c];
// 记忆化存储
memo[r][c] = ans;
return ans;
}
}
562. 행렬에서 가장 긴 연속 1 선 세그먼트
솔루션 1 : DFS.
1을 만나면 끝점으로두고 네 방향으로 이동을 시작하고이 점을 끝점의 최대 결과로 반환합니다.
https://leetcode-cn.com/problems/longest-line-of-consecutive-one-in-matrix/solution/ju-zhen-zhong-zui-chang-de-lian-xu-1xian-duan-by- 엘/
class Solution {
public int longestLine(int[][] M) {
if (M == null || M.length == 0 || M[0].length == 0)
return 0;
int ans = 0;
int[][] horizontal = new int[M.length][M[0].length];
int[][] vertical = new int[M.length][M[0].length];
int[][] diagonal = new int[M.length][M[0].length];
int[][] antidiagonal = new int[M.length][M[0].length];
for (int i = 0; i != M.length; ++i) {
for (int j = 0; j != M[0].length; ++j) {
if (M[i][j] == 0) {
horizontal[i][j] = 0;
vertical[i][j] = 0;
diagonal[i][j] = 0;
antidiagonal[i][j] = 0;
} else {
horizontal[i][j] = j > 0 ? horizontal[i][j - 1] + 1 : 1;
vertical[i][j] = i > 0 ? vertical[i - 1][j] + 1 : 1;
diagonal[i][j] = i > 0 && j > 0 ? diagonal[i - 1][j - 1] + 1 : 1;
antidiagonal[i][j] = i > 0 && j < M[0].length - 1 ? antidiagonal[i - 1][j + 1] + 1 : 1;
ans = Math.max(ans, horizontal[i][j]);
ans = Math.max(ans, vertical[i][j]);
ans = Math.max(ans, diagonal[i][j]);
ans = Math.max(ans, antidiagonal[i][j]);
}
}
}
return ans;
}
}
91. 디코딩 방법
class Solution {
//状态定义:dp[i]为第i个位置解码方法的总数
public int numDecodings(String s) {
char[] chars = s.toCharArray();
if (chars[0] == '0') return 0;
int[] dp = new int[chars.length];
dp[0] = 1;
for (int i = 1; i < chars.length; i++) {
if (chars[i] == '0') {
//如果前一位不是1或者2,显然无法解码
if (chars[i - 1] != '1' && chars[i - 1] != '2') return 0;
//如果前一位是1或者2
dp[i] = i == 1 ? 1 : dp[i - 2];
} else if (chars[i - 1] == '1' || (chars[i - 1] == '2' && chars[i] >= '1' && chars[i] <= '6')) {
dp[i] = i == 1 ? dp[i - 1] + 1 : dp[i - 1] + dp[i - 2];
} else {
dp[i] = dp[i - 1];
}
}
return dp[chars.length - 1];
}
}
https://leetcode-cn.com/problems/decode-ways/solution/san-chong-jie-fa-dfsyi-wei-dong-tai-gui-tfvin/