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订阅,干货很多,能坚持跟下来会很有收获的。

posted @ 2020-12-15 12:03  米罗{mirror}  阅读(42)  评论(0编辑  收藏  举报