ARTS习惯(4)
米罗说
-
干难事必有所得
-
舍近求远,不珍惜身边已有的做法是愚蠢的
-
光说不练,假把式;光练不说,傻把式
Algorithm
每周至少做一个Leetcode算法题
【题目来源】
求最大子矩阵大小,左程云《程序员代码面试指南:IT名企算法与数据结构题目最优解(第2版)》
【题目】
给定一个整型矩阵map,其中的值只有0和1两种,求其中全是1的所有矩形区域中,最大的矩形区域为1的数量。
【例子】
// 全是1的最大矩形包含3个1
1 1 1 0
// 矩阵1 ,全是1的最大矩形有6个1
1 0 1 1
1 1 1 1
1 1 1 0
【解答】
步骤1:建立height数组。我们以【例子】的矩阵1为例,height数组表示:逐行切割矩阵,以切割的行做为底,统计每列的连续1的个数。切割矩阵第一行时,height = {1,0,1,1},切割矩阵第二行时,height = {2,1,2,2,2},切割矩阵第三行时,height = {3,2,3,0}
步骤2:单调栈求每列最大能左右扩多大。 以height = {3,4,5,4,3,6}为例说明,
1.生成栈stack存放height数组的索引位置,从左至右遍历height数组
2.栈的压入规则:栈单调递减,遍历到当前值height[i]时,height[i]>height[stack.peek()]
3.栈的弹出规则:height[i]<=height[stack.peek()]时,弹出栈顶位置,直到满足压入规则,即height[i]>height[stack.peek()]
4.最大矩形:j位置的最大矩形为(i-k-1)*height[j],注:j:当前弹出的栈顶位置,i:当前位置,k:弹出栈顶j后,新的栈顶。证明见求最大子矩阵大小
参考代码如下:
package com.pengluo.zcy_algorithm;
import java.util.Stack;
public class A16_MaxRecSize {
public static int maxRecSize(int[][] map) {
if (map == null || map[0].length ==0 || map.length == 0) {
return 0;
}
int[] height = new int[map[0].length];
int maxSize = 0;
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
height[j] = map[i][j] == 0 ? 0 : height[j] + 1;
}
// 逐行切割,刷新最大值
maxSize = Math.max(maxRecFromBottom(height), maxSize);
}
return maxSize;
}
public static int maxRecFromBottom(int[] height) {
if (height.length == 0 || height ==null){
return 0;
}
int maxArea = 0;
Stack<Integer> stack = new Stack<Integer>();
for (int i = 0; i < height.length; i++) {
while(!stack.isEmpty() && height[stack.peek()]>height[i]) {
int j = stack.pop();
int k = stack.isEmpty() ? -1 : stack.peek();
int curArea = (i - k - 1 ) * height[j];
maxArea = Math.max(curArea, maxArea);
}
stack.push(i);
}
while(!stack.isEmpty()) {
int j = stack.pop();
int k = stack.isEmpty() ? -1 : stack.peek();
int curArea = (height.length - k - 1) * height[j];
}
return maxArea;
}
public static void main(String[] args) {
int[][] map = {{1,0,1,1},{1,1,1,1},{1,1,1,0}};
System.out.println(maxRecSize(map));
}
}
【思考讨论】
- 思考公式(i-k-1)*height[j]的推导
Review
阅读并点评至少1篇英文技术文章
【原文】:Head First Java(2nd Editon)CH8 Serious Polymorphism
【译文】:英文版原汁原味,语义准确,本书的写作风格幽默,容易理解。读者应重点关注作者是如何一步一步带你带你分析问题的,不必纠结细枝末节的东西。读者也可移步Head First Java(第二版·中文版)。
【点评】:
多态主题围绕:继承父类和实现接口展开,看完本章后豁然开朗,一些模棱两可的概念一下就清晰了。
-
The compiler won’t let you instantiate an abstract class(抽象类不能实例化)
-
An abstract method has no body! (抽象方法没有{},分号结尾,需要在具体类中override)
abstract public class Dog { abstract public void eat(); }
-
Every class in Java extends class Object(Java中任何类直接或间接的都继承Object)
-
multiple inheritance has Deadly Diamond of Death(Java不允许多继承,死亡菱形)
-
A Java interface is like a 100% pure abstract class.(接口是百分百的抽象类,Java允许实现多个接口)
-
Polymorphism(多态)
-
多使用抽象的父类做方法参数、返回类型、数组 赋值
abstract public class Animal {} public Dog extends Animal {} public Cat extends Animal {} // 数组 Animal[] animals = new Animal[3]; animals[0] = new Dog(); animals[1] = new Cat(); // 方法入参 public void add(Animal a) { }
-
强转类型之前,instanceof 判断类型
if (d instanceof Dog) { Dog dog = (Dog) }
-
-
2个常见接口
// save state to a file
public class Dog implements Serializable
// run its method in a separate thread of execution
public class Dog implements Runnable
Tip
学习至少一个技术技巧
参考我之前写的一篇Mybatis逆向工程生成代码的博客。自动化配置(1):利用Mybatis-generator自动生成实体类,接口,mapper.xml
Share
分享一篇有观点和思考的技术文章
分享极客时间上的一个算法专栏,谷歌算法工程师主讲的,数据结构和算法之美
目前已突破10W订阅,干货很多,能坚持跟下来会很有收获的。