catalogue
Maximum sum of 1 continuous subarrays
two Divide and conquer (official solution -- line segment tree)
3. Dynamic planning + temporary variables
4. Dynamic planning + in situ modification
1. Dynamic programming + 2D array
2. Open one more row and one more column 0 optimization code
dynamic programming
Maximum sum of 1 continuous subarrays
1. Violence Act
Violence law | O(N2) | O(1) |
two Divide and conquer (official solution -- line segment tree)
Divide and conquer | O(NlogN) | O(logN) |
This divide and conquer method is similar to the pushUp operation of "solving the longest common ascending subsequence problem with line segment tree". Maybe the reader hasn't touched the segment tree yet. It doesn't matter. The content of method 2 assumes that you don't have any basis for the segment tree. Of course, if readers are interested, it is recommended to read the segment tree interval merging method to solve the "interval longest continuous rising sequence problem" and "interval maximum sub segment sum problem" asked many times, which is still very interesting.
First define an operation get(a, l,r) Represents a query aa sequence The maximum sub segment sum in the [l,r] interval, then the final required answer is get(nums, 0, nums.size() - 1). How to divide and conquer to achieve this operation?
For an interval [l, R], let's take M = ⌊ (l+r)/2 ⌋, for the interval [l,m] and [m+1,r] Divide and conquer solution. When recursion goes deep layer by layer until the interval length is reduced to one Recursion "starts to pick up" when. Consider how to pass it at this time [l,m] Interval information and The information of [M + 1, R] interval is combined into interval [l,r][l,r] Information about. The two most critical issues are:
- What information do you want to maintain?
- How do you combine this information?
For an interval [l,r], we can maintain four quantities:
- Sum express [l,r] Inside l Is the maximum sub segment of the left endpoint and
- rSum express [l,r] Inside rr is the maximum sub segment sum of the right endpoint
- mSum express [l,r] Maximum sub segment and
- iSum express [l,r] Interval sum of
hereinafter referred to as [l,m] by [l,r] Left subinterval of [m+1,r] by [l,r] Right subinterval of. Consider how to maintain these quantities? (how to combine the information of the left and right subintervals to obtain [l,r] Information about the project)?
For length one Interval of [i,i], the values of the four quantities are the same as nums[i] equal. For lengths greater than one Interval of:
- First of all, the best maintenance is Isum, interval [l,r] of iSum It's equal to the left subinterval iSum Add "right sub interval" iSum.
- about There are two possibilities for the lSum of [l,r], which is either equal to the lSum of the "left subinterval" lSum, or iSum equal to "left subinterval" Add "right sub interval" lSum, whichever is greater.
- about [l,r] of rSum, similarly, it is either equal to the value of the "right subinterval" rSum, or iSum equal to "right subinterval" Add rSum of "left sub interval", and the two are larger.
- When the above three quantities are calculated, it is easy to calculate [l,r] mSum Yes. We can consider Msum of [l,r] Whether the corresponding interval crosses m——
- May not cross m. That is to say [l,r] mSum for It may be the mSum of the "left sub interval" And mSum of "right subinterval" One of;
- May also cross m. It may be rSum of "left subinterval" And lSum of "right subinterval" Sum.
- The last three are larger.
In this way, the problem has been solved.
class Solution { public class Status { public int lSum, rSum, mSum, iSum; public Status(int lSum, int rSum, int mSum, int iSum) { this.lSum = lSum; this.rSum = rSum; this.mSum = mSum; this.iSum = iSum; } } public int maxSubArray(int[] nums) { return getInfo(nums, 0, nums.length - 1).mSum; } public Status getInfo(int[] a, int l, int r) { if (l == r) { return new Status(a[l], a[l], a[l], a[l]); } int m = (l + r) >> 1; Status lSub = getInfo(a, l, m); Status rSub = getInfo(a, m + 1, r); return pushUp(lSub, rSub); } public Status pushUp(Status l, Status r) { int iSum = l.iSum + r.iSum; int lSum = Math.max(l.lSum, l.iSum + r.lSum); int rSum = Math.max(r.rSum, r.iSum + l.rSum); int mSum = Math.max(Math.max(l.mSum, r.mSum), l.rSum + r.lSum); return new Status(lSum, rSum, mSum, iSum); } }
3. Dynamic planning + temporary variables
Dynamic programming analysis:
-
Status definition: Set dynamic programming list dp , dp[i] represents the element num [i] Is the maximum sum of contiguous subarrays at the end.
- Why is the maximum sum defined Element must be included in DP [i] nums[i]: guarantee dp[i] Recursive to Correctness of dp[i+1]; If not nums[i], the recursion does not meet the requirements of the topic Continuous subarray requirement.
- Let dp be a one-dimensional array, where the value of dp[i] represents the largest subarray and sum of the array composed of the first I numbers .
- Transfer equation: If dp[i − 1] ≤ 0 , Description dp[i − 1] Yes, dp[i] Negative contribution, i.e. dp[i − 1]+nums[i] Not as good as nums[i] itself is large.
-
When dp[i − 1] > 0: execute dp[i]=dp[i − 1]+nums[i];
-
When dp[i − 1] ≤ 0: execute dp[i]=nums[i];
-
- Initial state: dp[0] = nums[i];, Namely The maximum sum of consecutive subarrays ending in num [0] is num [0] .
- Return value: Return dp The maximum value in the list represents the global maximum value.
4. Dynamic planning + in situ modification
Reduced space complexity:
- because dp[i] only with dp[i-1] and nums[i] So the original array can be nums be used as dp List, i.e. directly in nums You can modify it on the.
- As omitted dp The list uses additional space, so the space complexity from O(N) lower O(1) .
Complexity analysis:
- Time complexity O(N) : Linear ergodic array nums To get results, use o (n) Time.
- Spatial complexity O(1) : Use extra space of constant size.
2 maximum value of gifts
1. Dynamic programming + 2D array
package jzof.Day09; /** * @author ahan * @create_time 2021-11-11-11:45 morning * There is a gift in each grid of an m*n chessboard, and each gift has a certain value (value greater than 0). * You can start from the upper left corner of the chessboard to take the gifts in the grid, and move one grid to the right or down at a time until you reach the lower right corner of the chessboard. * Given the value of a chessboard and the gifts on it, please calculate the maximum value of gifts you can get? */ public class _47 { public static void main(String[] args) { int [][] nums = new int[][]{ {1,3,1}, {1,5,1}, {4,2,1} }; System.out.println(new _47().maxValue(nums)); } public int maxValue(int[][] grid) { int m = grid.length; int n = grid[0].length; int[][] dp = new int[m][n]; dp[0][0] = grid[0][0]; for (int i = 1; i < m; i++) { dp[i][0] = dp[i-1][0] + grid[i][0]; } for (int i = 1; i < n; i++) { dp[0][i] = dp[0][i-1] + grid[0][i]; } for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1])+grid[i][j]; } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { System.out.print(dp[i][j]+"\t"); } System.out.println(" "); } return dp[m-1][n-1]; } }
It's the same idea and method as the boss, hahaha ~ but the boss modified it in situ...
Space efficiency is not much worse~
Complexity analysis:
- Time complexity O(MN) : M,N Row height and column width of matrix respectively; Dynamic programming needs to traverse the whole grid Matrix, using O(MN) time.
- Space complexity O(1) : In place modification uses additional space of constant size.
2. Open one more row and one more column 0 optimization code
public int maxValue(int[][] grid) { int row = grid.length; int column = grid[0].length; //dp[i][j] represents the maximum value from grid[0][0] to grid[i - 1][j - 1] int[][] dp = new int[row + 1][column + 1]; for (int i = 1; i <= row; i++) { for (int j = 1; j <= column; j++) { dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1]; } } return dp[row][column]; }