Summary of leetcode dynamic programming 1
1-longest palindrome substring
Title Link: Title Link stamp here!!!
The test passed several times. The AC code is as follows.
The first use of violence enumeration, double pointer to judge palindromes, timeout.
The second time, I thought it was OK to flip the string and compare it with the original string to find the longest common substring. In fact, it was not. Through 177 test cases, 3 failed.
For the third time, the recursive expression of dynamic programming, accept, is as follows:
dp[i][j]=true;
dp[i][j] = dp[i+1][j-1];
A string from i to i, that is, a single, must be a palindrome.
Otherwise, judge whether the character at position I on the left is the same as that at position j on the right. If it is different, it must not be a palindrome string. If it is the same, j-I < 3, it must not exceed three characters, and it must be a palindrome string. If j-I > = 3, dp[i][j] = dp[i+1][j-1]
public class Solution { public static String longestPalindrome(String s) { int len = s.length() ; if(len==1){ return s ; } int max = 1, index=0 ; boolean [][]dp = new boolean [len][len] ; for(int i=0; i<len; i++){ dp[i][i] = true ; } for(int L=2; L<=len; L++){ for(int i=0; i<len; i++){ int j = L + i - 1 ; if(j>=len){ break ; } if(s.charAt(i) != s.charAt(j)){ dp[i][j] = false ; }else{ if(j-i<3){ dp[i][j] = true ; }else{ dp[i][j] = dp[i+1][j-1] ; } } if(dp[i][j] && j-i+1>max){ max = j - i + 1; index = i ; } } } return s.substring(index, index+max) ; } }
2-bracket generation
Title Link: Title Link stamp here!!!
This question can also be AC with dfs. According to the remaining number of left and right parentheses, add left and right parentheses until the remaining number is 0.
class Solution { List<String> list = new ArrayList<>() ; public List<String> generateParenthesis(int n) { dfs(n,n, "") ; return list ; } public void dfs(int left, int right, String str){ if(left==0 && right==0){ list.add(str) ; return ; } if(left>0){ dfs(left-1, right, str+ "(") ; } if(right>left){ dfs(left, right-1, str+ ")") ; } } }
Dynamic planning AC code is as follows:
Recursive idea:
"(" + permutation and combination of all parentheses when i=p + ")" + permutation and combination of all parentheses when i=q
import java.util.LinkedList; import java.util.List; class Solution { public List<String> generateParenthesis(int n) { LinkedList <LinkedList<String>> result = new LinkedList<>() ; LinkedList<String> list1 = new LinkedList<>() ; list1.add("") ; LinkedList<String> list2 = new LinkedList<>() ; list2.add("()") ; result.add(list1) ; result.add(list2) ; for(int i=2; i<=n; i++){ LinkedList<String> temp = new LinkedList<>() ; for(int j=0; j<i; j++){ LinkedList<String> str1 = result.get(j) ; LinkedList<String> str2 = result.get(i-j-1) ; for(String s1 : str1){ for(String s2 : str2){ String res = "(" + s1 + ")" + s2 ; temp.add(res) ; } } } result.add(temp) ; } return result.get(n) ; } }
3 - climbing stairs
Title Link: Title Link stamp here!!!
Water, relax. The AC code is as follows:
Thought: this problem can also be solved recursively, but it will time out. Use a simple recursive formula. When it is greater than or equal to 3 stairs, f[i] = f[i-1] + f[i-2], when the first stair f[1]=1, and the second stair f[2]=2;
class Solution { public int climbStairs(int n) { int [] f = new int [n+1] ; if(n==1){ return 1 ; } if(n == 2){ return 2 ; } f[1] = 1 ; f[2] = 2 ; for(int i=3; i<=n; i++){ f[i] = f[i-1] + f[i-2] ; } return f[n] ; } }
4-ugly number
Title Link: Poke here!!!
Three finger acupuncture, AC code is as follows:
The first three pointers point to the initial position. Select the values of the three pointers in turn, multiply the minimum values of 2, 3 and 5, and add them to the list in turn.
import java.util.List ; class Solution { public int nthUglyNumber(int n) { int ans = 1 ; if(n==1){ return 1 ; } List<Integer> list = new ArrayList<>() ; list.add(1) ; int idx2 = 0 ; int idx3 = 0 ; int idx5 = 0 ; for(int i=0; i<n-1; i++){ int a = list.get(idx2)*2 ; int b = list.get(idx3)*3 ; int c = list.get(idx5)*5 ; int min = Math.min(Math.min(a,b),c) ; list.add(min) ; if(list.get(list.size()-1) == a){ idx2 ++ ; } if(list.get(list.size()-1) == b){ idx3 ++ ; } if(list.get(list.size()-1) == c){ idx5 ++ ; } } return list.get(list.size()-1) ; } }
Written in this way, it is more concise. The AC code is as follows:
class Solution { public int nthUglyNumber(int n) { int idx2=0, idx3=0, idx5=0; int [] dp = new int [n] ; dp[0] = 1 ; for(int i=1; i<n; i++){ dp[i] = Math.min(2*dp[idx2],Math.min(3*dp[idx3], 5*dp[idx5])) ; if(dp[i] == 2 * dp[idx2]){ idx2++ ; } if(dp[i] == 3 * dp[idx3]){ idx3 ++ ; } if(dp[i] == 5 * dp[idx5]){ idx5 ++ ; } } return dp[n-1] ; } }
5 - Yanghui triangle
Title Link: Title Link stamp here!!!
Very simple dynamic programming, the first row, the first column and the last column of dp [] [] are all 1, and the rest satisfy d[i][j] = dp[i-1][j-1]+dp[i-1][j]
The AC code is as follows:
class Solution { public List<List<Integer>> generate(int numRows) { int [][] dp = new int [numRows][numRows] ; List<List<Integer>> res = new ArrayList<>() ; for(int i=0; i<numRows; i++){ List<Integer> list = new ArrayList<>() ; for(int j=0; j<=i; j++){ if(i==0 || j==0 || i==j){ dp[i][j] = 1 ; list.add(dp[i][j]) ; }else{ dp[i][j] = dp[i-1][j-1] + dp[i-1][j] ; list.add(dp[i][j]) ; } } res.add(list) ; } return res ; } }
6 - Yanghui triangle||
The title link is as follows: Title Link stamp here!!!
This question is similar to Yang Hui's triangle in the previous question. I won't repeat it, but go directly to AC code
class Solution { public List<Integer> getRow(int rowIndex) { List<Integer> list = new ArrayList<>() ; int [][]dp = new int [rowIndex+1][rowIndex+1] ; for(int i=0; i<=rowIndex; i++){ for(int j=0; j<=i; j++){ if(i==0 || j==0 || i==j){ dp[i][j] = 1 ; }else{ dp[i][j] = dp[i-1][j-1] + dp[i-1][j] ; } if(i==rowIndex){ list.add(dp[i][j]) ; } } } return list ; } }
7 - Maximum subarray sum
Title Link: Title Link stamp here!!!
This problem is different from the longest increasing subsequence. The subsequence is continuous, but the subsequence does not require continuity. Each time judge whether the current array value is greater than 0. If it is greater than 0, it will be added to the next array to find the maximum value in the final array. The AC code is as follows:
class Solution { public int maxSubArray(int[] nums) { int max = nums[0] ; for(int i=0; i<nums.length-1; i++){ if(nums[i]>0){ nums[i+1] += nums[i] ; } if(nums[i+1] > max){ max = nums[i+1] ; } } return max ; } }
8-longest increasing subsequence
Recursive expression: DP [i] = math max(dp[j]+1, dp[i])
First, fill the dp array with 1, initialize to increment subsequence as itself, then fix I, and traverse j from the beginning in turn. If num [i] > num [J], dp[i] becomes math Max (dp [J] + 1, dp[i]). Finally, scan the dp array to find the maximum value, which is the length of the longest increasing subsequence.
Complexity O(N^2)
The AC code is as follows:
class Solution { public int lengthOfLIS(int[] nums) { int [] dp = new int [nums.length] ; int res = Integer.MIN_VALUE ; Arrays.fill(dp, 1) ; for(int i=1; i<nums.length; i++){ for(int j=0; j<i; j++){ if(nums[i] > nums[j]){ dp[i] = Math.max(dp[j]+1, dp[i]) ; } } } for(int i=0; i<dp.length; i++){ res = Math.max(dp[i], res) ; } return res ; } }
9-perfect square
Title Link: Title Link stamp here!!!
It's easy to find the recurrence formula, otherwise, it's very difficult. This problem, using dp array to record the least complete square used, is actually a knapsack problem.
The AC code is as follows:
class Solution { public int numSquares(int n) { int [] dp = new int [n+1] ; Arrays.fill(dp, Integer.MAX_VALUE) ; dp[0] = 0 ; for(int i=1; i<=n; i++){ for(int j=1; j*j<=i; j++){ dp[i] = Math.min(dp[i], dp[i-j*j]+1) ; } } return dp[n] ; } }
10 - change
Title Link: Title Link stamp here!!!
Like the complete square number, this problem is a knapsack problem. The AC code is as follows:
class Solution { public int coinChange(int[] coins, int amount) { int [] dp = new int [amount + 1] ; Arrays.fill(dp, Integer.MAX_VALUE) ; dp[0] = 0 ; for(int i=1; i<=amount; i++){ for(int j=0; j<coins.length; j++){ if((i-coins[j]>=0) && (dp[i-coins[j]] != Integer.MAX_VALUE)){ dp[i] = Math.min(dp[i], dp[i-coins[j]]+1) ; } } } if(dp[amount] == Integer.MAX_VALUE){ return -1 ; } return dp[amount] ; } }