今日份算法题,就都写在一起吧。
LeetCode:303区域和检索 - 数组不可变
题目
给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。
示例:
给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange() sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0, 5) -> -3说明:
- 你可以假设数组不可变。
- 会多次调用 sumRange 方法。
大量的调用sumRange方法,那最直接的求和方式一定是会超时的,方法也很简单,遍历数组的同时,计算出当前的数字累加和,存放到sumArray数组中,当调用sumRange方法时,只需要计算 sumArray[j] - sumArray[i] + nums[i] 或者是 sumArray[j[ - sumArray[i-1] 即可。
代码
class NumArray {
static int[] sumArray ;
static int[] array;
public NumArray(int[] nums) {
sumArray = new int[nums.length];
array = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
array[i] = nums[i];
if (i == 0) sumArray[i] = nums[i];
else sumArray[i] = nums[i] + sumArray[i-1];
}
}
public int sumRange(int i, int j) {
return sumArray[j] - sumArray[i] + array[i];
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(i,j);
*/
LeetCode:84. 柱状图中最大的矩形
题目
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为
[2,1,5,6,2,3]
。图中阴影部分为所能勾勒出的最大矩形面积,其面积为
10
个单位。
示例:
输入: [2,1,5,6,2,3] 输出: 10
这道题是看了解题报告之后做的。
当我们的柱形图中的柱子是按照升序排列,及 4,5,6,7,8 ,那么最大面积比较容易算得 :也就是 4*4 5*3 6*2 8*1 中的最大数16。
可题目中的数据不一定会是升序排列的,那我们就要想办法将它排列成升序,这里就用到了栈,来维护一个升序柱状图,当某个柱子想要入栈,那么需要判断该柱高和栈顶的大小,如果大于栈顶数,那么该柱子直接入栈;那如果是小于栈顶,栈顶就需要出栈,出栈的同时计算一下该柱子的面积,出栈直到栈顶小于该柱高,柱子进栈,出栈了的柱子同时也将柱高变成和刚刚的柱子一样的高,重新入栈。
2 1 5 6 2 3 maxArea = 0
此时栈为空 2 可以直接入栈 , 此时栈: 2
此时栈顶为2 1 与栈顶2比较 1 < 2 , 栈顶出栈 maxArea = 2 * 1=2, 1 入栈 2变为1 入栈 此时栈:1 1
此时栈顶为1 5 与栈顶1比较 5 > 1 , 可以入栈, 此时栈: 1 1 5
此时栈顶为5 6 与栈顶1比较 6 > 5 , 可以入栈, 此时栈: 1 1 5 6
此时栈顶为6 2 与栈顶1比较 2 < 6 , 栈顶出栈 maxArea = max(2 , 6 * 1 ) = 6,
此时栈顶为5 同样2<5 需要出栈, maxArear = max (6, 5*2) = 10 (这里的5 * 2 : 5是柱子的高 2是出栈了的两个柱子)
此时栈顶为1 现在2 > 1 可以入栈了, 连通前两个出栈的5 6 都变为 2 一起入栈,现在的栈: 1 1 2 2 2
此时栈顶为2 现在3 > 2 可以入栈, 此时栈 1 1 2 2 2 3
现在的maxArea = 10;
现在栈中是一个升序的柱状图了,可以暗账上面所说的来进行计算 1*6 1*5 2*4 2*3 2*2 3*1 最大数为8 但是8 < 10 所以maxArea还是10
代码
class Solution {
public int largestRectangleArea(int[] heights) {
Stack<Integer> stack = new Stack();
int result = 0;
for (int i = 0; i < heights.length; i++) {
if (stack.isEmpty() || stack.peek() < heights[i]){
stack.push(heights[i]);
continue;
}
int count = 0;
int temp = stack.peek();
while (temp > heights[i]){
stack.pop();
result = Math.max(result,temp * ++count);
if (stack.isEmpty()) break;
temp = stack.peek();
}
while (count-- >= 0) {
stack.push(heights[i]);
}
}
System.out.println(stack);
int count = 0;
while (!stack.isEmpty()){
result = Math.max(result,stack.pop() * ++count);
}
return result;
}
}
LeetCode:85. 最大矩形
题目
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例:
输入: [ ["1","0","1","0","0"], ["1","0","1","1","1"], ["1","1","1","1","1"], ["1","0","0","1","0"] ] 输出: 6
这个题和上面的题时有些联系的,这个题可以看为上面的题的扩展,可以把这个二维数组想像成多个柱形图,按照上面的输入样例为例,可以看为4个柱形图,第一行为底,第二行为底,第三行为底,第四行为底,4个,然后用上面84题的解法来解。
代码
class Solution {
public static int maximalRectangle(char[][] matrix) {
if (matrix.length == 0 )return 0;
int result = 0;
int[][] nums = new int[matrix.length][matrix[0].length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (i == 0 && matrix[i][j] == '1'){
nums[i][j] = 1;
}else if (matrix[i][j] == '1'){
nums[i][j] = nums[i-1][j] + 1;
}
}
result = Math.max(result,maxArea(nums[i]));
}
return result;
}
public static int maxArea (int[] heights){
Stack<Integer> stack = new Stack();
int result = 0;
for (int i = 0; i < heights.length; i++) {
if (stack.isEmpty() || stack.peek() < heights[i]){
stack.push(heights[i]);
continue;
}
int count = 0;
int temp = stack.peek();
while (temp > heights[i]){
stack.pop();
result = Math.max(result,temp * ++count);
if (stack.isEmpty()) break;
temp = stack.peek();
}
while (count-- >= 0)
stack.push(heights[i]);
}
int count = 0;
while (!stack.isEmpty())
result = Math.max(result,stack.pop() * ++count);
return result;
}
}