ARTS习惯(5)

Algorithm

每周至少做一个Leetcode算法题

第1道


【题目来源】

T2:实现Singleton模式,何海涛《剑指Offer》

【题目】

设计一个类,我们只能生成该类的一个实例。

【解答】

不好的解法一:只适用于单线程

/**
 * 
 * 单例:线程不安全
 */

public class Singleton1 {
          private static Singleton1 instance = null;

          private Singleton1() {}

          public static Singleton1 getInstance() {
              if ( instance == null ) {
                  return new Singleton1();
              }
              return instance;
          }
}

不好的解法二:适用于多线程,但效率不高

/**
 * 单例:对getInstance()方法加锁,效率不高(instance!=null时,没必要加锁)
 *
 */

public class Singleton2 {
          private static volatile Singleton2 instance = null;

          private Singleton2() {}

          public static synchronized Singleton2 getInstance() {
              if (instance == null ) {
                  return new Singleton2();
              }
              return instance;
          }
}

推荐的解法一: 懒汉式-加锁前后两次判断实例是否已存在

/**
 * 懒汉式:对类加锁 + 双重检查
 */

public class Singleton4 {
            // volatile作用:禁止指令重排
          private static volatile Singleton4 instance = null;

          private Singleton4() {}

          public static Singleton4 getInstance() {
              if (instance == null ) {
                  synchronized (Singleton4.class) {
                      // A、B两个线程同时满足第一个if检查,A线程先获得锁,创建实例后,若没有二次if检查,B线程可能再次创建实例,单例目标失败
                      if ( instance == null ) {
                          return new Singleton4();
                      }
                  }
              }
              return instance;
          }
}

推荐的解法二: 饿汉式

public class Singleton5 {
    // JVM加载Singleton5类时,就创建了唯一的Singleton5对象
    // 线程安全
    private static Singleton5 instance = new Singleton5();

    private Singleton5() {}

    public static Singleton5 getInstance() {
        return instance;
    }
}

推荐的解法三: 静态内部类

/**
 * 懒汉式:静态内部类实现
 */
public class Singleton6 {

    private Singleton6() {}

    private static class SingleHolder {
        private static final Singleton6 instance = new Singleton6();
    }

    public static Singleton6 getInstance() {
        return SingleHolder.instance;
    }

}

第2道


【题目来源】

T3:二维数组中的查找,何海涛《剑指Offer》

【题目】

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

例子

// 给定二维数组,输入10,返回true;输入5,返回false
1,2,8,9
2,4,9,12
4,7,10,13
6,8,11,15

【解答】

  • 举例分析法

  • 排除法:小删行,大删列

    步骤

    1)初始猜测值guess选取二维数组右上角9;

    2)guess=9和目标值10比较,9小那么剔除9所在的,同时下移一步,因为9左边和上边的值都比9小,不可能找到10

    3)guess=12和目标值10比较,12大那么剔除所在的,同时左移一步,因为12右边和下标的值都比12大,不可能找到10

    4)guess=9和目标值10比较,9小那么剔除9所在的,同时下移一步

    5)guess=10等于目标值10,返回true,结束

public class FindInSortedMatrix {

    /**
     *
     * @param arr 二维数组
     * @param search 查找目标值
     * @return true:search存在;false:search不存在
     */
    public boolean isExist(int[][] arr, int search) {
        if (arr == null ) {
            return false;
        }
        int row = arr.length;
        int col = arr[0].length;
        // 选右上角为遍历起点
        int i = col -1;
        int j = 0;
        while (i >= 0 && j < row) {
            if (arr[i][j] == search) {
                return true;
            } else if (arr[i][j] > search) {
                i--;
            } else {
                j++;
            }
        }
        return false;
    }
}

思考

  • 思考遍历起点放在其他三个顶点是否可行?

  • 思考时间复杂度是多少?

Review

阅读并点评至少1篇英文技术文章

【原文】:Java Exception Handling: A Tutorial on How to Catch Errors and Improve Performance

【译文】:

【点评】:

作者:Rafal Kuć

Exception Class Hierarchy(异常的类层级结构)

层级结构图

如何抛异常

// create exception
throw new IOException();
// declare exception
throws IOException

throw

package com.pengluo.arts;

import java.io.*;

public class week5_exception {
    public File openFile(String path) throws IOException {
      File file = new File(path);
      if (!file.exists()) {
          throw new IOException();
      }
      return file;
    }
}

re-throw

package com.pengluo.arts;

import java.io.IOException;

public class RethrowException {

    public static void main(String[] args) throws IOException {
        RethrowException exec = new RethrowException();
        exec.run();
    }

    public void run() throws IOException {
        try {
            methodThrowingIOE();
        } catch (IOException ioe) {
           throw ioe; // re-throw 捕获到的ioe
        }
    }

    public void methodThrowingIOE() throws IOException {
        throw new IOException();
    }
}

如何处理异常

要么Handle:try-catch,要么Declare:throws,二者必须选其一

try-catch 块

注意catch块的执行顺序,粒度更细的异常类(specialized)要放在粒度更粗(general)面,否则specialized捕捉不到

finally 块

一定执行的代码块,且最后执行,为了避免因return 、break、continue造成需要清除的资源未清除设计,finally中用来关闭资源,文件流...。此外,try代码块中禁止return

try-with-resources

使用try-with-sources的class需要实现java.lang.AutoCloseable接口,然后上面在finally代码块的关闭资源功能就交给JVM处理。

Tip

学习至少一个技术技巧

Git的学习,教程参考廖雪峰的Git教程,本周的技术技巧分享有点偷懒了!

Share

分享一篇有观点和思考的技术文章

Java自动装箱的分析

米罗说

  • 不要浪费太多的时间在模仿”马云人“,成功不可以复制

  • 阅读-思考-写作的训练人人都需要掌握

原文地址:https://www.cnblogs.com/PengLuo22/p/14173318.html