目录
一,3200. 三角形的最大高度
二,3195. 包含所有 1 的最小矩形面积 I
三,3196. 最大化子数组的总成本
四,3197. 包含所有 1 的最小矩形面积 II
一,3200. 三角形的最大高度
本题是一道模拟题,可以先排序再用两个变量枚举最大值和最小值,不断比较,返回最小值,代码如下:
class Solution {public double minimumAverage(int[] nums) {Arrays.sort(nums);int n = nums.length;double ans = 50.0;int i = 0, j = n - 1;while(i < j){ans = Math.min(ans, (nums[i] + nums[j])/2.0);i++;j--;}return ans;}
}
二,3195. 包含所有 1 的最小矩形面积 I
本题求最小矩形的面积,就是求它的长和宽,即求它的上下左右,代码如下:
class Solution {public int minimumArea(int[][] grid) {int n = grid.length, m = grid[0].length;int left=m, right=0, top=n, bottom=0;for(int i=0; i<n; i++){for(int j=0; j<m; j++){if(grid[i][j] == 1){left = Math.min(left, j);right = Math.max(right, j);top = Math.min(top, i);bottom = Math.max(bottom, i);}}}return (right-left+1)*(bottom-top+1);}
}
三,3196. 最大化子数组的总成本
本题可以使用选或不选来做,即选择第 i 个数是在上一个子数组中(选),还是以它为起点重开了一个子数组(不选),所以我们需要一个参数 i 来确定下标,此外,要计算子数组的cost(l,r),我们还需要一个参数 j 来判断该数是加还是减,定义dfs(i,j):[0,i] 的最大总成本,且由 j 可得知,如果选,当前数是加还是减(j==0 ? + : -):
- 选,第 i 个数是在上一个子数组中,那么接下来要判断的是第 i + 1 个数选或不选,且 j^1,(j^1就是将0变1,1变0),即下一个状态是 dfs(i+1,j^1)
- 不选,第 i 个是新子数组的开头,那么接下来要判断的是第 i + 1 个数选或不选,注意如果第i+1个数要选的话,那么一定是减法( j = 1),即下一个状态是 dfs(i+1, 1)
代码如下:
class Solution {public long maximumTotalCost(int[] nums) {int n = nums.length;memo = new long[n][2];for(long[] r : memo) Arrays.fill(r, -1);return dfs(0, 0, nums);}long[][] memo;long dfs(int i, int j, int[] nums){if(i == nums.length) return 0;if(memo[i][j] != -1) return memo[i][j];return memo[i][j] = Math.max(dfs(i+1, j^1, nums) + (j==0?1:-1)*nums[i], dfs(i+1, 1, nums)+nums[i]);}
}
记忆化 1:1 改成递推
由上述代码可知:
- f [i][j]定义:[0,i] 的最大总成本,且由 j 可得知,如果选,当前数是加还是减(j==0 ? - : +)
- 递推公式 f[i][j] = Math.max( f[ i+1 ][ j^1 ] + (j==0?-1:1)*nums[i],f[i+1][1]+nums[i])
- 当 j = 0 时,f[i][0] = Math.max(f[i+1][1] - nums[i],f[i+1][1] + nums[i]) = f[i+1][1] + nums[i]
- 当 j = 1 时,f[i][1] = Math.max(f[i+1][0] - nums[i],f[i+1][1] + nums[i])
- 答案是f[0][0]
由递推公式可知,要得到f[i][j]就必须先得到f[i+1][j],所以需要倒着遍历,代码如下:
class Solution {public long maximumTotalCost(int[] nums) {int n = nums.length;long[][] f = new long[n+1][2];for(int i=n-1; i>=0; i--){f[i][0] = f[i+1][1] + nums[i];f[i][1] = Math.max(f[i+1][0] - nums[i], f[i+1][1] + nums[i]);}return f[0][0];}
}
四,3197. 包含所有 1 的最小矩形面积 II
本题可以直接暴力求解,题目要求三个不重叠的矩形,并没有要求每个矩形必须有1,所以我们可以将该矩形分成三个部分,在使用T2的方法求最小面积,就可以得到答案,我们一共有6种分法:
但是我们只需要写上面三个就行,因为下面三个可以由上面三个矩形向右旋转90度获得,代码如下:
class Solution {public int minimumArea(int[][] grid, int x1, int x2, int y1, int y2) {int left=y2, right=0, top=x2, bottom=0;for(int i=x1; i<x2; i++){for(int j=y1; j<y2; j++){if(grid[i][j] == 1){left = Math.min(left, j);right = Math.max(right, j);top = Math.min(top, i);bottom = Math.max(bottom, i);}}}return (right-left+1)*(bottom-top+1);}public int Sum(int[][] grid) {int n = grid.length, m = grid[0].length;int ans = n*m;if(n >= 3){for(int i=1; i<n; i++){for(int j=i+1; j<n; j++){//上中下int res = minimumArea(grid, 0, i, 0, m);res += minimumArea(grid, i, j, 0, m);res += minimumArea(grid, j, n, 0, m);ans = Math.min(ans, res);}}}if(n>=2 && m>=2){for(int i=1; i<n; i++){for(int j=1; j<m; j++){//上左右int res = minimumArea(grid, 0, i, 0, m);res += minimumArea(grid, i, n, 0, j);res += minimumArea(grid, i, n, j, m);ans = Math.min(ans, res);//左右下res = minimumArea(grid, 0, i, 0, j);res += minimumArea(grid, 0, i, j, m);res += minimumArea(grid, i, n, 0, m);ans = Math.min(ans, res);}}}return ans;}public int[][] rotate(int[][] grid){int n = grid.length, m = grid[0].length;int[][] a = new int[m][n];for(int i=0; i<n; i++){for(int j=0; j<m; j++){a[j][n-i-1] = grid[i][j];}}return a;}public int minimumSum(int[][] grid) {return Math.min(Sum(grid), Sum(rotate(grid)));}
}