auto commit

This commit is contained in:
CyC2018 2018-03-17 10:34:17 +08:00
parent 0967a9ab23
commit a2cf6fc9f9
2 changed files with 94 additions and 43 deletions

View File

@ -1,5 +1,6 @@
<!-- GFM-TOC --> <!-- GFM-TOC -->
* [第二章 面试需要的基础知识](#第二章-面试需要的基础知识) * [前言](#前言)
* [面试需要的基础知识](#面试需要的基础知识)
* [2. 实现 Singleton](#2-实现-singleton) * [2. 实现 Singleton](#2-实现-singleton)
* [3. 数组中重复的数字](#3-数组中重复的数字) * [3. 数组中重复的数字](#3-数组中重复的数字)
* [4. 二维数组中的查找](#4-二维数组中的查找) * [4. 二维数组中的查找](#4-二维数组中的查找)
@ -17,7 +18,7 @@
* [13. 机器人的运动范围](#13-机器人的运动范围) * [13. 机器人的运动范围](#13-机器人的运动范围)
* [14. 剪绳子](#14-剪绳子) * [14. 剪绳子](#14-剪绳子)
* [15. 二进制中 1 的个数](#15-二进制中-1-的个数) * [15. 二进制中 1 的个数](#15-二进制中-1-的个数)
* [第三章 高质量的代码](#第三章-高质量的代码) * [高质量的代码](#高质量的代码)
* [16. 数值的整数次方](#16-数值的整数次方) * [16. 数值的整数次方](#16-数值的整数次方)
* [17. 打印从 1 到最大的 n 位数](#17-打印从-1-到最大的-n-位数) * [17. 打印从 1 到最大的 n 位数](#17-打印从-1-到最大的-n-位数)
* [18.1 在 O(1) 时间内删除链表节点](#181-在-o1-时间内删除链表节点) * [18.1 在 O(1) 时间内删除链表节点](#181-在-o1-时间内删除链表节点)
@ -30,7 +31,7 @@
* [24. 反转链表](#24-反转链表) * [24. 反转链表](#24-反转链表)
* [25. 合并两个排序的链表](#25-合并两个排序的链表) * [25. 合并两个排序的链表](#25-合并两个排序的链表)
* [26. 树的子结构](#26-树的子结构) * [26. 树的子结构](#26-树的子结构)
* [第四章 解决面试题的思路](#第四章-解决面试题的思路) * [解决面试题的思路](#解决面试题的思路)
* [27. 二叉树的镜像](#27-二叉树的镜像) * [27. 二叉树的镜像](#27-二叉树的镜像)
* [28.1 对称的二叉树](#281-对称的二叉树) * [28.1 对称的二叉树](#281-对称的二叉树)
* [28.2 平衡二叉树](#282-平衡二叉树) * [28.2 平衡二叉树](#282-平衡二叉树)
@ -46,7 +47,7 @@
* [36. 二叉搜索树与双向链表](#36-二叉搜索树与双向链表) * [36. 二叉搜索树与双向链表](#36-二叉搜索树与双向链表)
* [37. 序列化二叉树](#37-序列化二叉树) * [37. 序列化二叉树](#37-序列化二叉树)
* [38. 字符串的排列](#38-字符串的排列) * [38. 字符串的排列](#38-字符串的排列)
* [第五章 优化时间和空间效率](#第五章-优化时间和空间效率) * [优化时间和空间效率](#优化时间和空间效率)
* [39. 数组中出现次数超过一半的数字](#39-数组中出现次数超过一半的数字) * [39. 数组中出现次数超过一半的数字](#39-数组中出现次数超过一半的数字)
* [40. 最小的 K 个数](#40-最小的-k-个数) * [40. 最小的 K 个数](#40-最小的-k-个数)
* [41.1 数据流中的中位数](#411-数据流中的中位数) * [41.1 数据流中的中位数](#411-数据流中的中位数)
@ -62,7 +63,7 @@
* [50. 第一个只出现一次的字符位置](#50-第一个只出现一次的字符位置) * [50. 第一个只出现一次的字符位置](#50-第一个只出现一次的字符位置)
* [51. 数组中的逆序对](#51-数组中的逆序对) * [51. 数组中的逆序对](#51-数组中的逆序对)
* [52. 两个链表的第一个公共结点](#52-两个链表的第一个公共结点) * [52. 两个链表的第一个公共结点](#52-两个链表的第一个公共结点)
* [第六章 面试中的各项能力](#第六章-面试中的各项能力) * [面试中的各项能力](#面试中的各项能力)
* [53 数字在排序数组中出现的次数](#53-数字在排序数组中出现的次数) * [53 数字在排序数组中出现的次数](#53-数字在排序数组中出现的次数)
* [54. 二叉搜索树的第 k 个结点](#54-二叉搜索树的第-k-个结点) * [54. 二叉搜索树的第 k 个结点](#54-二叉搜索树的第-k-个结点)
* [55 二叉树的深度](#55-二叉树的深度) * [55 二叉树的深度](#55-二叉树的深度)
@ -79,13 +80,29 @@
* [64. 求 1+2+3+...+n](#64-求-1+2+3++n) * [64. 求 1+2+3+...+n](#64-求-1+2+3++n)
* [65. 不用加减乘除做加法](#65-不用加减乘除做加法) * [65. 不用加减乘除做加法](#65-不用加减乘除做加法)
* [66. 构建乘积数组](#66-构建乘积数组) * [66. 构建乘积数组](#66-构建乘积数组)
* [第七章 两个面试案例](#第七章-两个面试案例) * [两个面试案例](#两个面试案例)
* [67. 把字符串转换成整数](#67-把字符串转换成整数) * [67. 把字符串转换成整数](#67-把字符串转换成整数)
* [68. 树中两个节点的最低公共祖先](#68-树中两个节点的最低公共祖先) * [68. 树中两个节点的最低公共祖先](#68-树中两个节点的最低公共祖先)
<!-- GFM-TOC --> <!-- GFM-TOC -->
# 第二章 面试需要的基础知识 # 前言
**变量命名规范**
- nums 表示数组matrix 表示矩阵;
- n 表示数组长度、字符串长度、树节点个数,以及其它具有一维性质的数据结构的元素个数;
- m, n 表示矩阵的行数和列数;
- first, last 表示闭区间:[first, last]
- begin, end 表示左闭右开区间:[begin, end)
- l, h 表示二分查找的闭区间:[l, h]
- ret 表示和结果相关的变量;
**复杂度简写说明**
O(nlog<sub>n</sub>) + O(n<sup>2</sup>),第一个指时间复杂度,第二个指空间复杂度。
# 面试需要的基础知识
## 2. 实现 Singleton ## 2. 实现 Singleton
@ -114,6 +131,8 @@ position-2 : (0,1,1,3,2,5) // nums[i] == nums[nums[i]], exit
遍历到位置 2 时,该位置上的数为 1但是第 1 个位置上已经有一个 1 的值了,因此可以知道 1 重复。 遍历到位置 2 时,该位置上的数为 1但是第 1 个位置上已经有一个 1 的值了,因此可以知道 1 重复。
复杂度O(n) + O(1)
```java ```java
public boolean duplicate(int[] nums, int length, int[] duplication) { public boolean duplicate(int[] nums, int length, int[] duplication) {
if (nums == null || length <= 0) return false; if (nums == null || length <= 0) return false;
@ -141,26 +160,34 @@ private void swap(int[] nums, int i, int j) {
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
```html ```html
Consider the following matrix:
[ [
[ 1, 5, 9], [1, 4, 7, 11, 15],
[10, 11, 13], [2, 5, 8, 12, 19],
[12, 13, 15] [3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
] ]
Given target = 5, return true.
Given target = 20, return false.
``` ```
**解题思路** **解题思路**
从右上角开始查找。因为矩阵中的一个数,它左边的数都比它来的小,下边的数都比它来的大。因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来改变行和列的下标,从而缩小查找区间。 从右上角开始查找。因为矩阵中的一个数,它左边的数都比它来的小,下边的数都比它来的大。因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来改变行和列的下标,从而缩小查找区间。
复杂度O(m + n) + O(1)
```java ```java
public boolean Find(int target, int [][] array) { public boolean Find(int target, int[][] matrix) {
if (array == null || array.length == 0 || array[0].length == 0) return false; if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;
int m = array.length, n = array[0].length; int m = matrix.length, n = matrix[0].length;
int row = 0, col = n - 1; int r = 0, c = n - 1; // 从右上角开始
while (row < m && col >= 0) { while (r <= m - 1 && c >= 0) {
if (target == array[row][col]) return true; if (target == matrix[r][c]) return true;
else if (target < array[row][col]) col--; else if (target > matrix[r][c]) r++;
else row++; else c--;
} }
return false; return false;
} }
@ -172,33 +199,37 @@ public boolean Find(int target, int [][] array) {
请实现一个函数,将一个字符串中的空格替换成“%20”。例如当字符串为 We Are Happy. 则经过替换之后的字符串为 We%20Are%20Happy。 请实现一个函数,将一个字符串中的空格替换成“%20”。例如当字符串为 We Are Happy. 则经过替换之后的字符串为 We%20Are%20Happy。
**题目要求**
以 O(1) 的空间复杂度和 O(n) 的时间复杂度来求解。
**解题思路** **解题思路**
从后向前改变字符串。 现在字符串尾部填充任意字符,使得字符串的长度等于将字符串替换之后的长度。因为一个空格要替换成三个字符(%20因此当遍历到一个空格时需要在尾部填充两个任意字符。
令 P1 指向字符串原来的末尾位置P2 指向字符串现在的末尾位置。P1 从后向前遍历,当遍历到一个空格时,就需要令 P2 指向的位置填充 02%(注意是逆序的),否则就填充上 P1 指向字符的值。
从后向前遍历时为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容。
复杂度O(n) + O(1)
<div align="center"> <img src="../pics//35b0caf8-6f34-49db-93ed-d505e9eb3d99.png"/> </div><br>
```java ```java
public String replaceSpace(StringBuffer str) { public String replaceSpace(StringBuffer str) {
int n = str.length(); int oldLen = str.length();
for (int i = 0; i < n; i++) { for (int i = 0; i < oldLen; i++) {
if (str.charAt(i) == ' ') { if (str.charAt(i) == ' ') {
str.append(" "); // 尾部填充两个 str.append(" ");
} }
} }
int idxOfOriginal = n - 1; int idxOfOld = oldLen - 1;
int idxOfNew = str.length() - 1; int idxOfNew = str.length() - 1;
while (idxOfOriginal >= 0 && idxOfNew > idxOfOriginal) { while (idxOfOld >= 0 && idxOfNew > idxOfOld) {
if (str.charAt(idxOfOriginal) == ' ') { char c = str.charAt(idxOfOld--);
if (c == ' ') {
str.setCharAt(idxOfNew--, '0'); str.setCharAt(idxOfNew--, '0');
str.setCharAt(idxOfNew--, '2'); str.setCharAt(idxOfNew--, '2');
str.setCharAt(idxOfNew--, '%'); str.setCharAt(idxOfNew--, '%');
} else { } else {
str.setCharAt(idxOfNew--, str.charAt(idxOfOriginal)); str.setCharAt(idxOfNew--, c);
} }
idxOfOriginal--;
} }
return str.toString(); return str.toString();
} }
@ -262,14 +293,15 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
```java ```java
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ListNode head = new ListNode(-1); // 头结点 // 头插法构建逆序链表
ListNode cur = listNode; ListNode head = new ListNode(-1);
while (cur != null) { while (listNode != null) {
ListNode next = cur.next; ListNode memo = listNode.next;
cur.next = head.next; listNode.next = head.next;
head.next = cur; head.next = listNode;
cur = next; listNode = memo;
} }
// 构建 ArrayList
ArrayList<Integer> ret = new ArrayList<>(); ArrayList<Integer> ret = new ArrayList<>();
head = head.next; head = head.next;
while (head != null) { while (head != null) {
@ -286,6 +318,25 @@ public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。 根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。
```html
For example, given
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
```
**解题思路**
中序遍历的第一个值为树根节点的值,使用这个值将前序遍历结果分成两部分,左部分为树的左子树前序遍历结果,右部分为树的右子树前序遍历的结果。
```java ```java
public TreeNode reConstructBinaryTree(int[] pre, int[] in) { public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
return reConstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1); return reConstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1);
@ -614,7 +665,7 @@ public int NumberOf1(int n) {
} }
``` ```
# 第三章 高质量的代码 # 高质量的代码
## 16. 数值的整数次方 ## 16. 数值的整数次方
@ -958,7 +1009,7 @@ private boolean isSubtree(TreeNode root1, TreeNode root2) {
} }
``` ```
# 第四章 解决面试题的思路 # 解决面试题的思路
## 27. 二叉树的镜像 ## 27. 二叉树的镜像
@ -1419,7 +1470,7 @@ private void backtracking(char[] chars, boolean[] hasUsed, StringBuffer s) {
} }
``` ```
# 第五章 优化时间和空间效率 # 优化时间和空间效率
## 39. 数组中出现次数超过一半的数字 ## 39. 数组中出现次数超过一半的数字
@ -1900,7 +1951,7 @@ public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
} }
``` ```
# 第六章 面试中的各项能力 # 面试中的各项能力
## 53 数字在排序数组中出现的次数 ## 53 数字在排序数组中出现的次数
@ -2323,7 +2374,7 @@ public int[] multiply(int[] A) {
} }
``` ```
# 第七章 两个面试案例 # 两个面试案例
## 67. 把字符串转换成整数 ## 67. 把字符串转换成整数

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB