剑指Offer: 顺时针打印矩阵
题目输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
思路 + 代码制造一个子函数,用来打印每一层。函数接收的参数是需要打印的行数跟列数,以及起始打印的位置(都是 n * n)。
特殊情况处理:打印行列错误、数组为空、单行或单列数组
1234567891011121314151617181920212223242526272829303132333435363738import java.util.ArrayList;public class Solution { public ArrayList<Integer> printMatrix(int [][] matrix) { ArrayList<Integer> res = new ArrayList<>(); printArr(m ...
剑指Offer 树的子结构
树的子结构输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路 + 代码涉及到二叉树相关的问题,首先想到是剑指O剑指递归。
由于二叉树是否为子树的判断,涉及到是否为 null的判断,因此需要建立子判定函数,避免空树情况产生干扰。
判断条件:
如果当前树节点与待判断树节点数值相同,则继续进行左右树的数值判断。直到两树中某一树为空。
否则分别对当前树的子树与右树跟带判断子树进行判定。
123456789101112131415161718192021222324252627282930313233/**public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; }}*/public class Solution { public boolean HasSubtr ...
设计模式: Java泛型
不要使用原始类型原始类型是Java(5之前)的历史遗留问题,之前集合对于类型在编译期间不进行检查,而在运行期进行类型检查。
这导致问题的定位困难,降低效率。
此后采用泛型解决这个问题,保证在编译期间进行检查。
例如List 类型是原始类型,而List< E >是泛型类型,指定了参数化类型为 E 类型。
List表明可以存储任何类型的对象,List< E > 是它的子类型,可以转化为List类型,但是丧失了安全性检查;而List< E > 却不是List< Object > 的子类型。List< Object > 只能是List< Object > 。
如果想实现类似于List等存储任何类型的对象, 可以利用无限制通配符类型(unbounded wildcard types)表示泛型类型,即List< ? > 。
泛型的几个注意点:
1. 类字面常量不允许使用泛型
数组String[].class、基本类型int.class、不带参数化类型的类List.class可以使用。
2. instanceof ...
Class文件长什么样
定义Class文件是Java语言实现跨平台的原材料,JVM(Java Vritual Machine)是实现跨平台的机器。
机器 + 原材料 = 跨平台。
不同的平台有自己的JVM,但是Class文件是一样的。
Class文件由java文件编译产生。
Class文件是由8位字节构成的二进制流,用类似于C语言结构体的伪结构来存储数据。
Class文件由无符号数和表组成。
无符号数用u1 u2 u4 u8来表示1 2 4 8个字节的无符号数。它用来表示数量值、数值、索引引用、按照UTF-8编码的字符串。
表是一种特殊的数据结构,它由表及无符号数组成,习惯表以_info结尾。
Class文件就是一张表,用来描述唯一确定的类或接口。
下面是从《深入了解JVM》中摘的Class文件的表结构。
图1 Class表结构
进入Class这张表首先我们写一个简单的类,叫做HelloClass。
1234567public class HelloClass { private int name; public int addName() { ret ...
剑指Offer 打印1到最大的n位数
题目打印1到最大的n位数。
示例:123输入 n = 1打印 1 2 3 4 5 6 7 8 9
思路 + 代码常规操作是暴力循环打印 1 到 n 位数,但是大数问题,存在数值溢出。
采用字符串或者数组存储中间结果。
思路1用一个 长度为 n 的数组存储,然后分别在最后一位计算,每次加一,逢十进一。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354public class PrintToNNumber { private static boolean increment(int[] nums) { if(nums==null || nums.length==0) return false; // 相加是否大于10 int overflow = 0; int len = nums.length; for (int i = l ...
LeetCode 15.三数之和
题目给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
1234567例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],满足要求的三元组集合为:[ [-1, 0, 1], [-1, -1, 2]]
思路+代码先排序,然后三数之和等于零必定有 1 到 2 个小于零, 1 到 2 个大于零。
然后我们采用双指针,先固定最小的一个数(负值);然后双指针再后面区间寻找两个数,与前面数相加等于零。
注意:因为不能包含重复三元组,在遍历过程中注意去重。保证每次遍历的数字与前面不一样即可(因为排序了)。
123456789101112131415161718192021222324252627282930313233343536373839404142434445class Solution { public List<List<Integer>> threeSum(int[] nu ...
Leetcode 674.最长连续子序列
题目给定一个未经排序的整数数组,找到最长且连续的的递增序列。
示例1:
1234输入: [1,3,5,4,7]输出: 3解释: 最长连续递增序列是 [1,3,5], 长度为3。尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开。
示例2:
123输入: [2,2,2,2,2]输出: 1解释: 最长连续递增序列是 [2], 长度为1。
注意:数组长度不会超过10000。
思路 + 代码思路1我的思路,用一个栈进行递增子序列长度的检查,用res缓存结果。
12345678910111213141516171819class Solution { public int findLengthOfLCIS(int[] nums) { if(nums==null || nums.length==0) return 0; Stack<Integer> s = new Stack<Integer>(); int res = 1; in ...
设计模式:Java类和接口
使类与成员可访问性最小成员(类、接口、方法、字段)的访问级别
private —— 该成员只能在声明它的顶级类内访问。
package-private —— 成员可以从被声明的包中的任何类中访问。从技术上讲,如果没有指定访问修饰符(接口成员除外,它默认是公共的),这是默认访问级别。
protected —— 成员可以从被声明的类的子类中访问(会受一些限制 [JLS, 6.6.2]),以及它声明的包中的任何类。
public —— 该成员可以从任何地方被访问。
公共类的实例字段很少情况下采用 public 修饰如果需要调用私有成员,就写一个方法。
12345private static final Thing[] PRIVATE_VALUES = { ... };public static final Thing[] values() { return PRIVATE_VALUES.clone();}
公共类中使用访问方法而不是访问属性虽然包内访问权限,如果只包内可见是可行的,也可以,同时可以避免视觉混乱,但是不提倡这样做。
123 ...
设计模式:Java方法
使用 try-with-resources调用用完需关闭的方法。实现了 AutoCloseable接口(由一个返回为 void的close组成)的资源可以使用try-with-resources方法。
AutoCloseable接口在Java的类库和第三方类库中许多类和接口都有实现或继承,例如 BufferedReader、InputStream、OutputStream 等。
123456789101112// examplestatic void copy(String src, String dst) throws IOException { try(InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)){ byte[] buf = new byte[BUFFER_SIZE]; int n; while((n = in.read(buf)) >= 0 ...
设计模式:Java创建对象
使用静态工厂方法代替构造方法静态工厂方法是一个静态方法,用来生成实例。例如:
12345678910111213// 单例模式public class Dog{ // 私有方法防止在外调用创建实例 private Dog(){ } private static class Inner(){ private static final Dog dog = new Dog(); } public static getInstance(){ return Inner.dog; }}
因为构造方法每次调用都需要新建一个对象,有些情况下不能满我们的要求。
而静态工厂方法生成对象有以下几个好处:
1. 名字更有意义。
from —— 类型转换方法,它接受单个参数并返回此类型的相应实例,例如:Date d = Date.from(instant);
of —— 聚合方法,接受多个参数并返回该类型的实例,并把他们合并在一起,例如:Set faceCard ...




