2018-09-19 10:01:05 +08:00
|
|
|
|
<!-- GFM-TOC -->
|
|
|
|
|
* [1. 字符串组合](#1-字符串组合)
|
2018-09-24 21:11:45 +08:00
|
|
|
|
* [2. 整数组合求和](#2-整数组合求和)
|
2018-09-19 10:01:05 +08:00
|
|
|
|
* [3. 数组中重复的数字](#3-数组中重复的数字)
|
2018-09-25 13:22:05 +08:00
|
|
|
|
* [4. 二维数组中的查找](#4-二维数组中的查找)
|
|
|
|
|
* [5. 替换空格](#5-替换空格)
|
2018-09-25 18:55:15 +08:00
|
|
|
|
* [6. 从尾到头打印链表](#6-从尾到头打印链表)
|
2018-09-26 19:29:55 +08:00
|
|
|
|
* [7. 重建二叉树](#7-重建二叉树)
|
|
|
|
|
* [8. 二叉树的下一个结点](#8-二叉树的下一个结点)
|
2018-09-27 20:31:45 +08:00
|
|
|
|
* [9. 用两个栈实现队列](#9-用两个栈实现队列)
|
|
|
|
|
* [10.1 斐波那契数列](#101-斐波那契数列)
|
|
|
|
|
* [10.2 跳台阶](#102-跳台阶)
|
|
|
|
|
* [10.3 矩形覆盖](#103-矩形覆盖)
|
|
|
|
|
* [10.4 变态跳台阶](#104-变态跳台阶)
|
2018-09-29 22:16:55 +08:00
|
|
|
|
* [11. 旋转数组的最小数字](#11-旋转数组的最小数字)
|
|
|
|
|
* [12. 矩阵中的路径](#12-矩阵中的路径)
|
2018-09-30 21:31:15 +08:00
|
|
|
|
* [13. 机器人的运动范围](#13-机器人的运动范围)
|
|
|
|
|
* [14. 剪绳子](#14-剪绳子)
|
2018-10-08 19:38:57 +08:00
|
|
|
|
* [15. 二进制中 1 的个数](#15-二进制中-1-的个数)
|
|
|
|
|
* [16. 数值的整数次方](#16-数值的整数次方)
|
2018-10-09 21:49:12 +08:00
|
|
|
|
* [17. 打印从 1 到最大的 n 位数](#17-打印从-1-到最大的-n-位数)
|
|
|
|
|
* [18.1 在 O(1) 时间内删除链表节点](#181-在-o1-时间内删除链表节点)
|
2018-10-10 19:09:46 +08:00
|
|
|
|
* [18.2 删除链表中重复的结点](#182-删除链表中重复的结点)
|
|
|
|
|
* [19. 正则表达式匹配](#19-正则表达式匹配)
|
2018-10-11 19:37:29 +08:00
|
|
|
|
* [20. 表示数值的字符串](#20-表示数值的字符串)
|
|
|
|
|
* [21. 调整数组顺序使奇数位于偶数前面](#21-调整数组顺序使奇数位于偶数前面)
|
2018-10-12 20:24:45 +08:00
|
|
|
|
* [22. 链表中倒数第 K 个结点](#22-链表中倒数第-k-个结点)
|
|
|
|
|
* [23. 链表中环的入口结点](#23-链表中环的入口结点)
|
2018-10-15 20:02:45 +08:00
|
|
|
|
* [24. 反转链表](#24-反转链表)
|
|
|
|
|
* [25. 合并两个排序的链表](#25-合并两个排序的链表)
|
2018-10-16 14:55:47 +08:00
|
|
|
|
* [26. 树的子结构](#26-树的子结构)
|
|
|
|
|
* [27. 二叉树的镜像](#27-二叉树的镜像)
|
2018-10-17 19:48:49 +08:00
|
|
|
|
* [28 对称的二叉树](#28-对称的二叉树)
|
|
|
|
|
* [29. 顺时针打印矩阵](#29-顺时针打印矩阵)
|
2018-10-18 19:46:55 +08:00
|
|
|
|
* [30. 包含 min 函数的栈](#30-包含-min-函数的栈)
|
|
|
|
|
* [31. 栈的压入、弹出序列](#31-栈的压入弹出序列)
|
2018-10-20 19:38:38 +08:00
|
|
|
|
* [32.1 从上往下打印二叉树](#321-从上往下打印二叉树)
|
|
|
|
|
* [32.2 把二叉树打印成多行](#322-把二叉树打印成多行)
|
2018-09-19 10:01:05 +08:00
|
|
|
|
|
|
|
|
|
* [参考文献](#参考文献)
|
|
|
|
|
<!-- GFM-TOC -->
|
|
|
|
|
|
|
|
|
|
# 1. 字符串组合
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
给定三种类型的小球P、Q、R,每种小球的数量分别为np、nq、nr个。现在想讲这些小球排成一条直线,但是不允许相同类型的小球相邻,问有多少种排序方法。
|
|
|
|
|
如若np=2,nq=1,nr=1则共有6种排列方式:PQRP、QPRP、PRQP、PRPQ、RPQP以及PQPR。如果无法组合出合适的结果,则输出0.
|
|
|
|
|
|
|
|
|
|
### 输入
|
|
|
|
|
```code
|
|
|
|
|
一行以空格相隔的三个数,分别表示为np、nq、nr。
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 输出
|
|
|
|
|
```code
|
|
|
|
|
排列方法的数量。
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 样例输入
|
|
|
|
|
```code
|
|
|
|
|
2 1 1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 样例输出
|
|
|
|
|
```code
|
|
|
|
|
6
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
本题采用一种比较直接的方式进行解题,分为如下步骤:
|
|
|
|
|
1. 求解给定P、Q、R个数的时候的全排列,提供`Python`提供的`itertools.permutations`来实现,此时肯定有很多重复。
|
|
|
|
|
2. 去掉重复的情况,通过`Python`提供的`set`来实现。
|
|
|
|
|
3. 通过遍历找出相邻元素重复的串。
|
|
|
|
|
4. 求两个集合的差集,即为答案。
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
import itertools
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
np, nq, nr = [int(k) for k in raw_input().split(" ")]
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
result = []
|
|
|
|
|
|
|
|
|
|
for i in itertools.permutations("P"*np + "Q"*nq + "R"*nr,np + nq + nr):
|
|
|
|
|
result.append(''.join(i))
|
|
|
|
|
|
|
|
|
|
result_same = []
|
|
|
|
|
|
|
|
|
|
for element in list(set(result)):
|
|
|
|
|
for j in range(1, len(element)):
|
|
|
|
|
if element[j-1] == element[j]:
|
|
|
|
|
result_same.append(element)
|
|
|
|
|
|
|
|
|
|
ret_list = list(set(result)^set(result_same))
|
|
|
|
|
|
|
|
|
|
print len(ret_list)
|
|
|
|
|
```
|
|
|
|
|
|
2018-09-24 21:11:45 +08:00
|
|
|
|
# 2. 整数组合求和
|
2018-09-19 10:01:05 +08:00
|
|
|
|
|
2018-09-24 21:11:45 +08:00
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
小米之家是成人糖果店。里面有很多便宜,好用,好玩的产品。中秋节到了,小米之家想给米粉准备一些固定金额大礼包。对于给定的一个金额,需要判断能不能用
|
|
|
|
|
不同种产品(一种产品在礼包最多出现一次)组合出来这个金额。聪明的你来帮帮米家的小伙伴吧。
|
|
|
|
|
|
|
|
|
|
### 输入
|
|
|
|
|
```code
|
|
|
|
|
输入N(N是正整数, N < = 200)
|
|
|
|
|
输入N个价格p(正整数, p <= 10000)用单空格分割
|
|
|
|
|
输入金额M(M是正整数,M <= 100000)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 输出
|
|
|
|
|
```code
|
|
|
|
|
能组合出来输出1
|
|
|
|
|
否则输出0
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 样例输入
|
|
|
|
|
```code
|
|
|
|
|
6
|
|
|
|
|
99 199 1999 10000 39 1499
|
|
|
|
|
10238
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 样例输出
|
|
|
|
|
```code
|
|
|
|
|
1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
本题采用一种比较直接的方式进行解题,分为如下步骤:
|
|
|
|
|
1. 对输入np进行排序,方便后面快速结束。
|
|
|
|
|
2. 求解给定np时候的0~n个组合的和,提供`Python`提供的`itertools.permutations`来实现。
|
|
|
|
|
3. 如果较小的数相加已经大于目标,可以提前跳出本次循环。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
import itertools
|
|
|
|
|
|
|
|
|
|
n = int(raw_input())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
np = [int(k) for k in raw_input().split(" ")]
|
|
|
|
|
np.sort()
|
|
|
|
|
|
|
|
|
|
sum_np = int(raw_input())
|
|
|
|
|
|
|
|
|
|
flag = 0
|
|
|
|
|
|
|
|
|
|
for i in range(n):
|
|
|
|
|
for j in itertools.permutations(np, i):
|
|
|
|
|
if sum(j) > sum_np:
|
|
|
|
|
continue;
|
|
|
|
|
if sum(j) == sum_np:
|
|
|
|
|
flag = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
print flag
|
|
|
|
|
```
|
2018-09-19 10:01:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 数组中重复的数字
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/623a5ac0ea5b4e5f95552655361ae0a8?tpId=13&tqId=11203&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为 7 的数组 {2, 3, 1, 0, 2, 5},那么对应的输出是第一个重复的数字 2。
|
|
|
|
|
|
|
|
|
|
要求复杂度为 O(N) + O(1),也就是时间复杂度 O(N),空间复杂度 O(1)。因此不能使用排序的方法,也不能使用额外的标记数组。牛客网讨论区这一题的首票答案使用 nums[i] + length 来将元素标记,这么做会有加法溢出问题。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素放到第 i 个位置上。
|
|
|
|
|
|
|
|
|
|
以 (2, 3, 1, 0, 2, 5) 为例:
|
|
|
|
|
|
|
|
|
|
```text-html-basic
|
|
|
|
|
position-0 : (2,3,1,0,2,5) // 2 <-> 1
|
|
|
|
|
(1,3,2,0,2,5) // 1 <-> 3
|
|
|
|
|
(3,1,2,0,2,5) // 3 <-> 0
|
|
|
|
|
(0,1,2,3,2,5) // already in position
|
|
|
|
|
position-1 : (0,1,2,3,2,5) // already in position
|
|
|
|
|
position-2 : (0,1,2,3,2,5) // already in position
|
|
|
|
|
position-3 : (0,1,2,3,2,5) // already in position
|
|
|
|
|
position-4 : (0,1,2,3,2,5) // nums[i] == nums[nums[i]], exit
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
遍历到位置 4 时,该位置上的数为 2,但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public boolean duplicate(int[] nums, int length, int[] duplication) {
|
|
|
|
|
if (nums == null || length <= 0)
|
|
|
|
|
return false;
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
|
while (nums[i] != i) {
|
|
|
|
|
if (nums[i] == nums[nums[i]]) {
|
|
|
|
|
duplication[0] = nums[i];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
swap(nums, i, nums[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void swap(int[] nums, int i, int j) {
|
|
|
|
|
int t = nums[i]; nums[i] = nums[j]; nums[j] = t;
|
|
|
|
|
}
|
|
|
|
|
```
|
2018-09-25 13:22:05 +08:00
|
|
|
|
|
2018-09-24 21:11:45 +08:00
|
|
|
|
```python
|
|
|
|
|
nums = [int(k) for k in raw_input().split(" ")]
|
|
|
|
|
print nums
|
|
|
|
|
|
|
|
|
|
def duplicate(nums):
|
|
|
|
|
if len(nums) <= 0:
|
|
|
|
|
return -1, False
|
|
|
|
|
for i in range(len(nums)):
|
|
|
|
|
while nums[i] != i:
|
|
|
|
|
if nums[i] == nums[nums[i]]:
|
|
|
|
|
return nums[i], True
|
2018-10-10 22:05:40 +08:00
|
|
|
|
index = nums[i]
|
|
|
|
|
nums[i], nums[index] = nums[index], nums[i]
|
2018-09-24 21:11:45 +08:00
|
|
|
|
# nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
|
|
|
|
|
return -1, False
|
|
|
|
|
|
|
|
|
|
print duplicate(nums)
|
|
|
|
|
```
|
2018-09-19 10:01:05 +08:00
|
|
|
|
|
2018-09-25 13:22:05 +08:00
|
|
|
|
# 4. 二维数组中的查找
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/abc3fe2ce8e146608e868a70efebf62e?tpId=13&tqId=11154&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
Consider the following matrix:
|
|
|
|
|
[
|
|
|
|
|
[1, 4, 7, 11, 15],
|
|
|
|
|
[2, 5, 8, 12, 19],
|
|
|
|
|
[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 和当前元素的大小关系来缩小查找区间。
|
|
|
|
|
|
|
|
|
|
复杂度:O(M + N) + O(1)
|
|
|
|
|
|
|
|
|
|
当前元素的查找区间为左下角的所有元素,例如元素 12 的查找区间如下:
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//f94389e9-55b1-4f49-9d37-00ed05900ae0.png" width="250"/> </div><br>
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public boolean Find(int target, int[][] matrix) {
|
|
|
|
|
if (matrix == null || matrix.length == 0 || matrix[0].length == 0)
|
|
|
|
|
return false;
|
|
|
|
|
int rows = matrix.length, cols = matrix[0].length;
|
|
|
|
|
int r = 0, c = cols - 1; // 从右上角开始
|
|
|
|
|
while (r <= rows - 1 && c >= 0) {
|
|
|
|
|
if (target == matrix[r][c])
|
|
|
|
|
return true;
|
|
|
|
|
else if (target > matrix[r][c])
|
|
|
|
|
r++;
|
|
|
|
|
else
|
|
|
|
|
c--;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
target = int(input())
|
|
|
|
|
|
|
|
|
|
# nums = [[1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30]]
|
|
|
|
|
|
|
|
|
|
nums = eval(input())
|
|
|
|
|
|
|
|
|
|
def find(target, matrix):
|
|
|
|
|
if len(matrix) == 0 or len(matrix[0]) == 0:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
rows, cols = len(matrix), len(matrix[0])
|
|
|
|
|
r, c = 0, cols - 1
|
|
|
|
|
|
|
|
|
|
while r <= rows - 1 and c >= 0:
|
|
|
|
|
if target == matrix[r][c]:
|
|
|
|
|
return True
|
|
|
|
|
elif target > matrix[r][c]:
|
|
|
|
|
r += 1
|
|
|
|
|
else:
|
|
|
|
|
c -= 1
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
print (find(target, nums))
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 5. 替换空格
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/4060ac7e3e404ad1a894ef3e17650423?tpId=13&tqId=11155&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
将一个字符串中的空格替换成 "%20"。
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
Input:
|
|
|
|
|
"We Are Happy"
|
|
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
"We%20Are%20Happy"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
在字符串尾部填充任意字符,使得字符串的长度等于替换之后的长度。因为一个空格要替换成三个字符(%20),因此当遍历到一个空格时,需要在尾部填充两个任意字符。
|
|
|
|
|
|
|
|
|
|
令 P1 指向字符串原来的末尾位置,P2 指向字符串现在的末尾位置。P1 和 P2从后向前遍历,当 P1 遍历到一个空格时,就需要令 P2 指向的位置依次填充 02%(注意是逆序的),否则就填充上 P1 指向字符的值。
|
|
|
|
|
|
|
|
|
|
从后向前遍是为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public String replaceSpace(StringBuffer str) {
|
|
|
|
|
int P1 = str.length() - 1;
|
|
|
|
|
for (int i = 0; i < P1 + 1; i++)
|
|
|
|
|
if (str.charAt(i) == ' ')
|
|
|
|
|
str.append(" ");
|
|
|
|
|
|
|
|
|
|
int P2 = str.length() - 1;
|
|
|
|
|
while (P1 >= 0 && P2 > P1) {
|
|
|
|
|
char c = str.charAt(P1--);
|
|
|
|
|
if (c == ' ') {
|
|
|
|
|
str.setCharAt(P2--, '0');
|
|
|
|
|
str.setCharAt(P2--, '2');
|
|
|
|
|
str.setCharAt(P2--, '%');
|
|
|
|
|
} else {
|
|
|
|
|
str.setCharAt(P2--, c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return str.toString();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
2018-09-25 17:28:14 +08:00
|
|
|
|
target = input()
|
2018-09-25 13:22:05 +08:00
|
|
|
|
|
2018-09-25 17:28:14 +08:00
|
|
|
|
print (target.replace(" ", "%20"))
|
2018-09-25 13:22:05 +08:00
|
|
|
|
```
|
2018-09-19 10:01:05 +08:00
|
|
|
|
|
2018-09-25 17:28:14 +08:00
|
|
|
|
|
2018-09-25 18:55:15 +08:00
|
|
|
|
# 6. 从尾到头打印链表
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/d0267f7f55b3412ba93bd35cfa8e8035?tpId=13&tqId=11156&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
输入链表的第一个节点,从尾到头反过来打印出每个结点的值。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//d99dc9e2-197c-4085-813d-7195da1c6762.png" width="300"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
### 使用栈
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
|
|
|
|
|
Stack<Integer> stack = new Stack<>();
|
|
|
|
|
while (listNode != null) {
|
|
|
|
|
stack.add(listNode.val);
|
|
|
|
|
listNode = listNode.next;
|
|
|
|
|
}
|
|
|
|
|
ArrayList<Integer> ret = new ArrayList<>();
|
|
|
|
|
while (!stack.isEmpty())
|
|
|
|
|
ret.add(stack.pop());
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 使用递归
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
|
|
|
|
|
ArrayList<Integer> ret = new ArrayList<>();
|
|
|
|
|
if (listNode != null) {
|
|
|
|
|
ret.addAll(printListFromTailToHead(listNode.next));
|
|
|
|
|
ret.add(listNode.val);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 使用头插法
|
|
|
|
|
|
|
|
|
|
利用链表头插法为逆序的特点。
|
|
|
|
|
|
|
|
|
|
头结点和第一个节点的区别:
|
|
|
|
|
|
|
|
|
|
- 头结点是在头插法中使用的一个额外节点,这个节点不存储值;
|
|
|
|
|
- 第一个节点就是链表的第一个真正存储值的节点。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
|
|
|
|
|
// 头插法构建逆序链表
|
|
|
|
|
ListNode head = new ListNode(-1);
|
|
|
|
|
while (listNode != null) {
|
|
|
|
|
ListNode memo = listNode.next;
|
|
|
|
|
listNode.next = head.next;
|
|
|
|
|
head.next = listNode;
|
|
|
|
|
listNode = memo;
|
|
|
|
|
}
|
|
|
|
|
// 构建 ArrayList
|
|
|
|
|
ArrayList<Integer> ret = new ArrayList<>();
|
|
|
|
|
head = head.next;
|
|
|
|
|
while (head != null) {
|
|
|
|
|
ret.add(head.val);
|
|
|
|
|
head = head.next;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
```
|
2018-09-26 19:29:55 +08:00
|
|
|
|
### 使用 Collections.reverse()
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
|
|
|
|
|
ArrayList<Integer> ret = new ArrayList<>();
|
|
|
|
|
while (listNode != null) {
|
|
|
|
|
ret.add(listNode.val);
|
|
|
|
|
listNode = listNode.next;
|
|
|
|
|
}
|
|
|
|
|
Collections.reverse(ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
```
|
2018-09-25 18:55:15 +08:00
|
|
|
|
|
|
|
|
|
```python
|
2018-09-25 18:59:00 +08:00
|
|
|
|
def printListFromTailToHead(listNode):
|
2018-09-25 18:55:15 +08:00
|
|
|
|
# write code here
|
|
|
|
|
l = list()
|
|
|
|
|
while listNode:
|
|
|
|
|
l.append(listNode.val)
|
|
|
|
|
listNode = listNode.next
|
|
|
|
|
l.reverse()
|
|
|
|
|
return l
|
|
|
|
|
```
|
2018-09-26 19:29:55 +08:00
|
|
|
|
# 7. 重建二叉树
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=13&tqId=11157&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
preorder = [3,9,20,15,7]
|
|
|
|
|
inorder = [9,3,15,20,7]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//8a4c6ad4-a816-47d1-b93f-7ca4f78ab67a.png" width="250"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序遍历结果,右部分为树的右子树中序遍历的结果。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// 缓存中序遍历数组每个值对应的索引
|
|
|
|
|
private Map<Integer, Integer> indexForInOrders = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
|
|
|
|
|
for (int i = 0; i < in.length; i++)
|
|
|
|
|
indexForInOrders.put(in[i], i);
|
|
|
|
|
return reConstructBinaryTree(pre, 0, pre.length - 1, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private TreeNode reConstructBinaryTree(int[] pre, int preL, int preR, int inL) {
|
|
|
|
|
if (preL > preR)
|
|
|
|
|
return null;
|
|
|
|
|
TreeNode root = new TreeNode(pre[preL]);
|
|
|
|
|
int inIndex = indexForInOrders.get(root.val);
|
|
|
|
|
int leftTreeSize = inIndex - inL;
|
|
|
|
|
root.left = reConstructBinaryTree(pre, preL + 1, preL + leftTreeSize, inL);
|
|
|
|
|
root.right = reConstructBinaryTree(pre, preL + leftTreeSize + 1, preR, inL + leftTreeSize + 1);
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# 返回构造的TreeNode根节点
|
2018-09-26 19:51:22 +08:00
|
|
|
|
def reConstructBinaryTree(self, pre, tin):
|
|
|
|
|
# write code here
|
|
|
|
|
if not pre or not tin:
|
|
|
|
|
return None
|
|
|
|
|
root = TreeNode(pre.pop(0))
|
|
|
|
|
index = tin.index(root.val)
|
|
|
|
|
root.left = self.reConstructBinaryTree(pre, tin[:index])
|
|
|
|
|
root.right = self.reConstructBinaryTree(pre, tin[index + 1:])
|
|
|
|
|
return root
|
2018-09-26 19:29:55 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 8. 二叉树的下一个结点
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/9023a0c988684a53960365b889ceaf5e?tpId=13&tqId=11210&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class TreeLinkNode {
|
|
|
|
|
int val;
|
|
|
|
|
TreeLinkNode left = null;
|
|
|
|
|
TreeLinkNode right = null;
|
|
|
|
|
TreeLinkNode next = null;
|
|
|
|
|
|
|
|
|
|
TreeLinkNode(int val) {
|
|
|
|
|
this.val = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
① 如果一个节点的右子树不为空,那么该节点的下一个节点是右子树的最左节点;
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//cb0ed469-27ab-471b-a830-648b279103c8.png" width="250"/> </div><br>
|
|
|
|
|
|
|
|
|
|
② 否则,向上找第一个左链接指向的树包含该节点的祖先节点。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//e143f6da-d114-4ba4-8712-f65299047fa2.png" width="250"/> </div><br>
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public TreeLinkNode GetNext(TreeLinkNode pNode) {
|
|
|
|
|
if (pNode.right != null) {
|
|
|
|
|
TreeLinkNode node = pNode.right;
|
|
|
|
|
while (node.left != null)
|
|
|
|
|
node = node.left;
|
|
|
|
|
return node;
|
|
|
|
|
} else {
|
|
|
|
|
while (pNode.next != null) {
|
|
|
|
|
TreeLinkNode parent = pNode.next;
|
|
|
|
|
if (parent.left == pNode)
|
|
|
|
|
return parent;
|
|
|
|
|
pNode = pNode.next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
2018-09-26 19:43:21 +08:00
|
|
|
|
def GetNext(self, pNode):
|
2018-09-27 20:38:17 +08:00
|
|
|
|
# write code here
|
|
|
|
|
# pNode is None
|
|
|
|
|
if not pNode:
|
|
|
|
|
return pNode
|
|
|
|
|
if pNode.right:
|
|
|
|
|
node = pNode.right
|
|
|
|
|
while node.left:
|
|
|
|
|
node = node.left
|
|
|
|
|
return node
|
|
|
|
|
else:
|
|
|
|
|
while pNode.next:
|
|
|
|
|
parent = pNode.next
|
|
|
|
|
if parent.left == pNode:
|
|
|
|
|
return parent
|
|
|
|
|
pNode = pNode.next
|
|
|
|
|
# pNode not have the next node
|
|
|
|
|
return None
|
2018-09-26 19:29:55 +08:00
|
|
|
|
```
|
2018-09-27 20:31:45 +08:00
|
|
|
|
# 9. 用两个栈实现队列
|
2018-09-26 19:29:55 +08:00
|
|
|
|
|
2018-09-27 20:31:45 +08:00
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6?tpId=13&tqId=11158&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
in 栈用来处理入栈(push)操作,out 栈用来处理出栈(pop)操作。一个元素进入 in 栈之后,出栈的顺序被反转。当元素要出栈时,需要先进入 out 栈,此时元素出栈顺序再一次被反转,因此出栈顺序就和最开始入栈顺序是相同的,先进入的元素先退出,这就是队列的顺序。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//5acf7550-86c5-4c5b-b912-8ce70ef9c34e.png" width="400"/> </div><br>
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
Stack<Integer> in = new Stack<Integer>();
|
|
|
|
|
Stack<Integer> out = new Stack<Integer>();
|
|
|
|
|
|
|
|
|
|
public void push(int node) {
|
|
|
|
|
in.push(node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int pop() throws Exception {
|
|
|
|
|
if (out.isEmpty())
|
|
|
|
|
while (!in.isEmpty())
|
|
|
|
|
out.push(in.pop());
|
|
|
|
|
|
|
|
|
|
if (out.isEmpty())
|
|
|
|
|
throw new Exception("queue is empty");
|
|
|
|
|
|
|
|
|
|
return out.pop();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.stack1 = []
|
|
|
|
|
self.stack2 = []
|
|
|
|
|
def push(self, node):
|
|
|
|
|
# write code here
|
|
|
|
|
self.stack1.append(node)
|
|
|
|
|
def pop(self):
|
|
|
|
|
# return xx
|
|
|
|
|
if self.stack2 == []:
|
|
|
|
|
while self.stack1:
|
|
|
|
|
self.stack2.append(self.stack1.pop())
|
|
|
|
|
return self.stack2.pop()
|
|
|
|
|
return self.stack2.pop()
|
|
|
|
|
```
|
|
|
|
|
# 10.1 斐波那契数列
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/c6c7742f5ba7442aada113136ddea0c3?tpId=13&tqId=11160&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
求斐波那契数列的第 n 项,n <= 39。
|
|
|
|
|
|
|
|
|
|
<div align="center"><img src="https://latex.codecogs.com/gif.latex?f(n)=\left\{\begin{array}{rcl}0&&{n=0}\\1&&{n=1}\\f(n-1)+f(n-2)&&{n>1}\end{array}\right."/></div> <br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
如果使用递归求解,会重复计算一些子问题。例如,计算 f(10) 需要计算 f(9) 和 f(8),计算 f(9) 需要计算 f(8) 和 f(7),可以看到 f(8) 被重复计算了。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//faecea49-9974-40db-9821-c8636137df61.jpg" width="300"/> </div><br>
|
|
|
|
|
|
|
|
|
|
递归是将一个问题划分成多个子问题求解,动态规划也是如此,但是动态规划会把子问题的解缓存起来,从而避免重复求解子问题。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int Fibonacci(int n) {
|
|
|
|
|
if (n <= 1)
|
|
|
|
|
return n;
|
|
|
|
|
int[] fib = new int[n + 1];
|
|
|
|
|
fib[1] = 1;
|
|
|
|
|
for (int i = 2; i <= n; i++)
|
|
|
|
|
fib[i] = fib[i - 1] + fib[i - 2];
|
|
|
|
|
return fib[n];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
考虑到第 i 项只与第 i-1 和第 i-2 项有关,因此只需要存储前两项的值就能求解第 i 项,从而将空间复杂度由 O(N) 降低为 O(1)。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int Fibonacci(int n) {
|
|
|
|
|
if (n <= 1)
|
|
|
|
|
return n;
|
|
|
|
|
int pre2 = 0, pre1 = 1;
|
|
|
|
|
int fib = 0;
|
|
|
|
|
for (int i = 2; i <= n; i++) {
|
|
|
|
|
fib = pre2 + pre1;
|
|
|
|
|
pre2 = pre1;
|
|
|
|
|
pre1 = fib;
|
|
|
|
|
}
|
|
|
|
|
return fib;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
由于待求解的 n 小于 40,因此可以将前 40 项的结果先进行计算,之后就能以 O(1) 时间复杂度得到第 n 项的值了。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class Solution {
|
|
|
|
|
private int[] fib = new int[40];
|
|
|
|
|
|
|
|
|
|
public Solution() {
|
|
|
|
|
fib[1] = 1;
|
|
|
|
|
fib[2] = 2;
|
|
|
|
|
for (int i = 2; i < fib.length; i++)
|
|
|
|
|
fib[i] = fib[i - 1] + fib[i - 2];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int Fibonacci(int n) {
|
|
|
|
|
return fib[n];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
2018-09-27 20:58:07 +08:00
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.fib = [0,1]
|
|
|
|
|
for i in range(2,40):
|
|
|
|
|
self.fib.append(self.fib[i-1]+self.fib[i-2])
|
|
|
|
|
def Fibonacci(self, n):
|
|
|
|
|
# write code here
|
|
|
|
|
return self.fib[n]
|
2018-09-27 20:31:45 +08:00
|
|
|
|
```
|
|
|
|
|
# 10.2 跳台阶
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/8c82a5b80378478f9484d87d1c5f12a4?tpId=13&tqId=11161&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int JumpFloor(int n) {
|
|
|
|
|
if (n <= 2)
|
|
|
|
|
return n;
|
|
|
|
|
int pre2 = 1, pre1 = 2;
|
|
|
|
|
int result = 1;
|
|
|
|
|
for (int i = 2; i < n; i++) {
|
|
|
|
|
result = pre2 + pre1;
|
|
|
|
|
pre2 = pre1;
|
|
|
|
|
pre1 = result;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
2018-09-28 16:10:15 +08:00
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def jumpFloor(self, number):
|
|
|
|
|
# write code here
|
|
|
|
|
if number == 0:
|
|
|
|
|
return number
|
|
|
|
|
pre1, pre2 = 1, 1
|
|
|
|
|
#result = 0
|
|
|
|
|
for i in range(number):
|
|
|
|
|
pre1, pre2 = pre2, pre1+pre2
|
|
|
|
|
return pre1
|
2018-09-27 20:31:45 +08:00
|
|
|
|
```
|
|
|
|
|
# 10.3 矩形覆盖
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/72a5a919508a4251859fb2cfb987a0e6?tpId=13&tqId=11163&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
我们可以用 2\*1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 n 个 2\*1 的小矩形无重叠地覆盖一个 2\*n 的大矩形,总共有多少种方法?
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int RectCover(int n) {
|
|
|
|
|
if (n <= 2)
|
|
|
|
|
return n;
|
|
|
|
|
int pre2 = 1, pre1 = 2;
|
|
|
|
|
int result = 0;
|
|
|
|
|
for (int i = 3; i <= n; i++) {
|
|
|
|
|
result = pre2 + pre1;
|
|
|
|
|
pre2 = pre1;
|
|
|
|
|
pre1 = result;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
2018-09-28 16:10:15 +08:00
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def rectCover(self, number):
|
|
|
|
|
# write code here
|
|
|
|
|
if number == 0:
|
|
|
|
|
return number
|
|
|
|
|
pre1, pre2 = 1, 1
|
|
|
|
|
#result = 0
|
|
|
|
|
for i in range(number):
|
|
|
|
|
pre1, pre2 = pre2, pre1+pre2
|
|
|
|
|
return pre1
|
2018-09-27 20:31:45 +08:00
|
|
|
|
```
|
|
|
|
|
# 10.4 变态跳台阶
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/22243d016f6b47f2a6928b4313c85387?tpId=13&tqId=11162&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级... 它也可以跳上 n 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int JumpFloorII(int target) {
|
|
|
|
|
int[] dp = new int[target];
|
|
|
|
|
Arrays.fill(dp, 1);
|
|
|
|
|
for (int i = 1; i < target; i++)
|
|
|
|
|
for (int j = 0; j < i; j++)
|
|
|
|
|
dp[i] += dp[j];
|
|
|
|
|
return dp[target - 1];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
2018-09-28 16:10:15 +08:00
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def jumpFloorII(self, number):
|
|
|
|
|
# write code here
|
|
|
|
|
if number <= 0:
|
|
|
|
|
return 0
|
|
|
|
|
return pow(2, number-1)
|
2018-09-27 20:31:45 +08:00
|
|
|
|
```
|
2018-09-29 22:16:55 +08:00
|
|
|
|
# 11. 旋转数组的最小数字
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=11159&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
|
|
|
|
|
|
|
|
|
|
例如数组 {3, 4, 5, 1, 2} 为 {1, 2, 3, 4, 5} 的一个旋转,该数组的最小值为 1。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
在一个有序数组中查找一个元素可以用二分查找,二分查找也称为折半查找,每次都能将查找区间减半,这种折半特性的算法时间复杂度都为 O(logN)。
|
|
|
|
|
|
|
|
|
|
本题可以修改二分查找算法进行求解:
|
|
|
|
|
|
|
|
|
|
- 当 nums[m] <= nums[h] 的情况下,说明解在 [l, m] 之间,此时令 h = m;
|
|
|
|
|
- 否则解在 [m + 1, h] 之间,令 l = m + 1。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int minNumberInRotateArray(int[] nums) {
|
|
|
|
|
if (nums.length == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
int l = 0, h = nums.length - 1;
|
|
|
|
|
while (l < h) {
|
|
|
|
|
int m = l + (h - l) / 2;
|
|
|
|
|
if (nums[m] <= nums[h])
|
|
|
|
|
h = m;
|
|
|
|
|
else
|
|
|
|
|
l = m + 1;
|
|
|
|
|
}
|
|
|
|
|
return nums[l];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
如果数组元素允许重复的话,那么就会出现一个特殊的情况:nums[l] == nums[m] == nums[h],那么此时无法确定解在哪个区间,需要切换到顺序查找。例如对于数组 {1,1,1,0,1},l、m 和 h 指向的数都为 1,此时无法知道最小数字 0 在哪个区间。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int minNumberInRotateArray(int[] nums) {
|
|
|
|
|
if (nums.length == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
int l = 0, h = nums.length - 1;
|
|
|
|
|
while (l < h) {
|
|
|
|
|
int m = l + (h - l) / 2;
|
|
|
|
|
if (nums[l] == nums[m] && nums[m] == nums[h])
|
|
|
|
|
return minNumber(nums, l, h);
|
|
|
|
|
else if (nums[m] <= nums[h])
|
|
|
|
|
h = m;
|
|
|
|
|
else
|
|
|
|
|
l = m + 1;
|
|
|
|
|
}
|
|
|
|
|
return nums[l];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int minNumber(int[] nums, int l, int h) {
|
|
|
|
|
for (int i = l; i < h; i++)
|
|
|
|
|
if (nums[i] > nums[i + 1])
|
|
|
|
|
return nums[i + 1];
|
|
|
|
|
return nums[l];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def minNumberInRotateArray(self, rotateArray):
|
|
|
|
|
# write code here
|
|
|
|
|
if len(rotateArray) == 0:
|
|
|
|
|
return 0
|
|
|
|
|
return min(rotateArray)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 12. 矩阵中的路径
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/c61c6999eecb4b8f88a98f66b273a3cc?tpId=13&tqId=11218&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
|
|
|
|
|
|
|
|
|
|
例如下面的矩阵包含了一条 bfce 路径。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//e31abb94-9201-4e06-9902-61101b92f475.png" width="300"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
private final static int[][] next = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
|
|
|
|
|
private int rows;
|
|
|
|
|
private int cols;
|
|
|
|
|
|
|
|
|
|
public boolean hasPath(char[] array, int rows, int cols, char[] str) {
|
|
|
|
|
if (rows == 0 || cols == 0)
|
|
|
|
|
return false;
|
|
|
|
|
this.rows = rows;
|
|
|
|
|
this.cols = cols;
|
|
|
|
|
boolean[][] marked = new boolean[rows][cols];
|
|
|
|
|
char[][] matrix = buildMatrix(array);
|
|
|
|
|
for (int i = 0; i < rows; i++)
|
|
|
|
|
for (int j = 0; j < cols; j++)
|
|
|
|
|
if (backtracking(matrix, str, marked, 0, i, j))
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean backtracking(char[][] matrix, char[] str, boolean[][] marked, int pathLen, int r, int c) {
|
|
|
|
|
if (pathLen == str.length)
|
|
|
|
|
return true;
|
|
|
|
|
if (r < 0 || r >= rows || c < 0 || c >= cols || matrix[r][c] != str[pathLen] || marked[r][c])
|
|
|
|
|
return false;
|
|
|
|
|
marked[r][c] = true;
|
|
|
|
|
for (int[] n : next)
|
|
|
|
|
if (backtracking(matrix, str, marked, pathLen + 1, r + n[0], c + n[1]))
|
|
|
|
|
return true;
|
|
|
|
|
marked[r][c] = false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private char[][] buildMatrix(char[] array) {
|
|
|
|
|
char[][] matrix = new char[rows][cols];
|
|
|
|
|
for (int i = 0, idx = 0; i < rows; i++)
|
|
|
|
|
for (int j = 0; j < cols; j++)
|
|
|
|
|
matrix[i][j] = array[idx++];
|
|
|
|
|
return matrix;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def hasPath(self, matrix, rows, cols, path):
|
|
|
|
|
# write code here
|
|
|
|
|
for i in range(rows):
|
|
|
|
|
for j in range(cols):
|
|
|
|
|
if matrix[i*cols+j] == path[0]:
|
|
|
|
|
if self.find(list(matrix),rows,cols,path[1:],i,j):
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
def find(self,matrix,rows,cols,path,i,j):
|
|
|
|
|
if not path:
|
|
|
|
|
return True
|
|
|
|
|
matrix[i*cols+j]='0'
|
|
|
|
|
if j+1<cols and matrix[i*cols+j+1]==path[0]:
|
|
|
|
|
return self.find(matrix,rows,cols,path[1:],i,j+1)
|
|
|
|
|
elif j-1>=0 and matrix[i*cols+j-1]==path[0]:
|
|
|
|
|
return self.find(matrix,rows,cols,path[1:],i,j-1)
|
|
|
|
|
elif i+1<rows and matrix[(i+1)*cols+j]==path[0]:
|
|
|
|
|
return self.find(matrix,rows,cols,path[1:],i+1,j)
|
|
|
|
|
elif i-1>=0 and matrix[(i-1)*cols+j]==path[0]:
|
|
|
|
|
return self.find(matrix,rows,cols,path[1:],i-1,j)
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def buildMatrix(self, matrix):
|
|
|
|
|
array = [[0]*self.cols for i in range(self.rows)]
|
|
|
|
|
for i in range(self.rows):
|
|
|
|
|
idx = 0
|
|
|
|
|
for j in range(self.cols):
|
|
|
|
|
array[i][j] = matrix[idx]
|
|
|
|
|
idx += 1
|
|
|
|
|
return array
|
|
|
|
|
```
|
2018-09-30 21:31:15 +08:00
|
|
|
|
# 13. 机器人的运动范围
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/6e5207314b5241fb83f2329e89fdecc8?tpId=13&tqId=11219&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
地上有一个 m 行和 n 列的方格。一个机器人从坐标 (0, 0) 的格子开始移动,每一次只能向左右上下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于 k 的格子。
|
|
|
|
|
|
|
|
|
|
例如,当 k 为 18 时,机器人能够进入方格 (35,37),因为 3+5+3+7=18。但是,它不能进入方格 (35,37),因为 3+5+3+8=19。请问该机器人能够达到多少个格子?
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
private static final int[][] next = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
|
|
|
|
|
private int cnt = 0;
|
|
|
|
|
private int rows;
|
|
|
|
|
private int cols;
|
|
|
|
|
private int threshold;
|
|
|
|
|
private int[][] digitSum;
|
|
|
|
|
|
|
|
|
|
public int movingCount(int threshold, int rows, int cols) {
|
|
|
|
|
this.rows = rows;
|
|
|
|
|
this.cols = cols;
|
|
|
|
|
this.threshold = threshold;
|
|
|
|
|
initDigitSum();
|
|
|
|
|
boolean[][] marked = new boolean[rows][cols];
|
|
|
|
|
dfs(marked, 0, 0);
|
|
|
|
|
return cnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void dfs(boolean[][] marked, int r, int c) {
|
|
|
|
|
if (r < 0 || r >= rows || c < 0 || c >= cols || marked[r][c])
|
|
|
|
|
return;
|
|
|
|
|
marked[r][c] = true;
|
|
|
|
|
if (this.digitSum[r][c] > this.threshold)
|
|
|
|
|
return;
|
|
|
|
|
cnt++;
|
|
|
|
|
for (int[] n : next)
|
|
|
|
|
dfs(marked, r + n[0], c + n[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initDigitSum() {
|
|
|
|
|
int[] digitSumOne = new int[Math.max(rows, cols)];
|
|
|
|
|
for (int i = 0; i < digitSumOne.length; i++) {
|
|
|
|
|
int n = i;
|
|
|
|
|
while (n > 0) {
|
|
|
|
|
digitSumOne[i] += n % 10;
|
|
|
|
|
n /= 10;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.digitSum = new int[rows][cols];
|
|
|
|
|
for (int i = 0; i < this.rows; i++)
|
|
|
|
|
for (int j = 0; j < this.cols; j++)
|
|
|
|
|
this.digitSum[i][j] = digitSumOne[i] + digitSumOne[j];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2018-09-30 21:35:18 +08:00
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.acc = 0
|
|
|
|
|
|
|
|
|
|
def movingCount(self, threshold, rows, cols):
|
|
|
|
|
# write code here
|
|
|
|
|
self.threshold = threshold
|
|
|
|
|
self.rows = rows
|
|
|
|
|
self.cols = cols
|
|
|
|
|
self.board = [[0 for _ in range(cols)] for _ in range(rows)]
|
|
|
|
|
|
|
|
|
|
self.traverse(0,0)
|
|
|
|
|
return self.acc
|
|
|
|
|
|
|
|
|
|
def block(self, r, c):
|
|
|
|
|
s = sum(map(int,str(r)+str(c)))
|
|
|
|
|
return s>self.threshold
|
|
|
|
|
|
|
|
|
|
def traverse(self, r, c):
|
|
|
|
|
if not (0<=r<self.rows and 0<=c<self.cols): return
|
|
|
|
|
if self.board[r][c]!=0: return
|
|
|
|
|
if self.board[r][c]==-1 or self.block(r,c):
|
|
|
|
|
self.board[r][c]=-1
|
|
|
|
|
return
|
|
|
|
|
self.board[r][c] = 1
|
|
|
|
|
self.acc += 1
|
|
|
|
|
self.traverse(r+1,c)
|
|
|
|
|
self.traverse(r-1,c)
|
|
|
|
|
self.traverse(r,c+1)
|
|
|
|
|
self.traverse(r,c-1)
|
|
|
|
|
```
|
|
|
|
|
|
2018-09-30 21:31:15 +08:00
|
|
|
|
# 14. 剪绳子
|
|
|
|
|
|
|
|
|
|
[Leetcode](https://leetcode.com/problems/integer-break/description/)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
把一根绳子剪成多段,并且使得每段的长度乘积最大。
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
n = 2
|
|
|
|
|
return 1 (2 = 1 + 1)
|
|
|
|
|
|
|
|
|
|
n = 10
|
|
|
|
|
return 36 (10 = 3 + 3 + 4)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
### 贪心
|
|
|
|
|
|
|
|
|
|
尽可能多剪长度为 3 的绳子,并且不允许有长度为 1 的绳子出现。如果出现了,就从已经切好长度为 3 的绳子中拿出一段与长度为 1 的绳子重新组合,把它们切成两段长度为 2 的绳子。
|
|
|
|
|
|
|
|
|
|
证明:当 n >= 5 时,3(n - 3) - 2(n - 2) = n - 5 >= 0。因此把长度大于 5 的绳子切成两段,令其中一段长度为 3 可以使得两段的乘积最大。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int integerBreak(int n) {
|
|
|
|
|
if (n < 2)
|
|
|
|
|
return 0;
|
|
|
|
|
if (n == 2)
|
|
|
|
|
return 1;
|
|
|
|
|
if (n == 3)
|
|
|
|
|
return 2;
|
|
|
|
|
int timesOf3 = n / 3;
|
|
|
|
|
if (n - timesOf3 * 3 == 1)
|
|
|
|
|
timesOf3--;
|
|
|
|
|
int timesOf2 = (n - timesOf3 * 3) / 2;
|
|
|
|
|
return (int) (Math.pow(3, timesOf3)) * (int) (Math.pow(2, timesOf2));
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2018-09-25 17:28:14 +08:00
|
|
|
|
|
2018-09-30 21:35:18 +08:00
|
|
|
|
```python
|
|
|
|
|
def integerBreak(n):
|
|
|
|
|
if n < 2:
|
|
|
|
|
return 0
|
|
|
|
|
if n == 2:
|
|
|
|
|
return 1
|
|
|
|
|
if n == 3:
|
|
|
|
|
return 2
|
|
|
|
|
timesOf3 = n // 3
|
|
|
|
|
if n - timesOf3 * 3 == 1:
|
|
|
|
|
timesOf3 -= 1
|
|
|
|
|
timesOf2 = (n - timesOf3 * 3) // 2
|
|
|
|
|
return pow(3, timesOf3) * pow(2, timesOf2)
|
|
|
|
|
```
|
2018-10-08 19:38:57 +08:00
|
|
|
|
# 15. 二进制中 1 的个数
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/8ee967e43c2c4ec193b040ea7fbb10b8?tpId=13&tqId=11164&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
输入一个整数,输出该数二进制表示中 1 的个数。
|
|
|
|
|
|
|
|
|
|
### n&(n-1)
|
|
|
|
|
|
|
|
|
|
该位运算去除 n 的位级表示中最低的那一位。
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
n : 10110100
|
|
|
|
|
n-1 : 10110011
|
|
|
|
|
n&(n-1) : 10110000
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
时间复杂度:O(M),其中 M 表示 1 的个数。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int NumberOf1(int n) {
|
|
|
|
|
int cnt = 0;
|
|
|
|
|
while (n != 0) {
|
|
|
|
|
cnt++;
|
|
|
|
|
n &= (n - 1);
|
|
|
|
|
}
|
|
|
|
|
return cnt;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Integer.bitCount()
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int NumberOf1(int n) {
|
|
|
|
|
return Integer.bitCount(n);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def NumberOf1(self, n):
|
|
|
|
|
# write code here
|
|
|
|
|
if n<0:
|
|
|
|
|
n=n&0xFFFFFFFF #把负号去掉,如果负号在后面会陷入死循环
|
|
|
|
|
return bin(n).count('1')
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def NumberOf1(self, n):
|
|
|
|
|
# write code here
|
|
|
|
|
return sum([(n>>i & 1) for i in range(0,32)])
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 16. 数值的整数次方
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/1a834e5e3e1a4b7ba251417554e07c00?tpId=13&tqId=11165&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
给定一个 double 类型的浮点数 base 和 int 类型的整数 exponent,求 base 的 exponent 次方。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
下面的讨论中 x 代表 base,n 代表 exponent。
|
|
|
|
|
|
|
|
|
|
<div align="center"><img src="https://latex.codecogs.com/gif.latex?x^n=\left\{\begin{array}{rcl}(x*x)^{n/2}&&{n\%2=0}\\x*(x*x)^{n/2}&&{n\%2=1}\end{array}\right."/></div> <br>
|
|
|
|
|
|
|
|
|
|
因为 (x\*x)<sup>n/2</sup> 可以通过递归求解,并且每次递归 n 都减小一半,因此整个算法的时间复杂度为 O(logN)。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public double Power(double base, int exponent) {
|
|
|
|
|
if (exponent == 0)
|
|
|
|
|
return 1;
|
|
|
|
|
if (exponent == 1)
|
|
|
|
|
return base;
|
|
|
|
|
boolean isNegative = false;
|
|
|
|
|
if (exponent < 0) {
|
|
|
|
|
exponent = -exponent;
|
|
|
|
|
isNegative = true;
|
|
|
|
|
}
|
|
|
|
|
double pow = Power(base * base, exponent / 2);
|
|
|
|
|
if (exponent % 2 != 0)
|
|
|
|
|
pow = pow * base;
|
|
|
|
|
return isNegative ? 1 / pow : pow;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def Power(self, base, exponent):
|
|
|
|
|
# write code here
|
|
|
|
|
flag = 0
|
|
|
|
|
if base == 0:
|
|
|
|
|
return False
|
|
|
|
|
if exponent == 0:
|
|
|
|
|
return 1
|
|
|
|
|
if exponent < 0:
|
|
|
|
|
flag = 1
|
|
|
|
|
result = 1
|
|
|
|
|
for i in range(abs(exponent)):
|
|
|
|
|
result *= base
|
|
|
|
|
if flag == 1:
|
|
|
|
|
result = 1 / result
|
|
|
|
|
return result
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def Power(self, base, exponent):
|
|
|
|
|
# write code here
|
|
|
|
|
return pow(base, exponent)
|
|
|
|
|
```
|
2018-09-30 21:35:18 +08:00
|
|
|
|
|
2018-10-08 19:50:30 +08:00
|
|
|
|
### 动态规划
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int integerBreak(int n) {
|
|
|
|
|
int[] dp = new int[n + 1];
|
|
|
|
|
dp[1] = 1;
|
|
|
|
|
for (int i = 2; i <= n; i++)
|
|
|
|
|
for (int j = 1; j < i; j++)
|
|
|
|
|
dp[i] = Math.max(dp[i], Math.max(j * (i - j), dp[j] * (i - j)));
|
|
|
|
|
return dp[n];
|
|
|
|
|
}
|
|
|
|
|
```
|
2018-10-09 21:49:12 +08:00
|
|
|
|
# 17. 打印从 1 到最大的 n 位数
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数即 999。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
由于 n 可能会非常大,因此不能直接用 int 表示数字,而是用 char 数组进行存储。
|
|
|
|
|
|
|
|
|
|
使用回溯法得到所有的数。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public void print1ToMaxOfNDigits(int n) {
|
|
|
|
|
if (n <= 0)
|
|
|
|
|
return;
|
|
|
|
|
char[] number = new char[n];
|
|
|
|
|
print1ToMaxOfNDigits(number, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void print1ToMaxOfNDigits(char[] number, int digit) {
|
|
|
|
|
if (digit == number.length) {
|
|
|
|
|
printNumber(number);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
number[digit] = (char) (i + '0');
|
|
|
|
|
print1ToMaxOfNDigits(number, digit + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void printNumber(char[] number) {
|
|
|
|
|
int index = 0;
|
|
|
|
|
while (index < number.length && number[index] == '0')
|
|
|
|
|
index++;
|
|
|
|
|
while (index < number.length)
|
|
|
|
|
System.out.print(number[index++]);
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
def numbersByRecursion(n,largest,result):
|
|
|
|
|
def recursion(num,largest,result):
|
|
|
|
|
if num <= largest:
|
|
|
|
|
result.append(num)
|
|
|
|
|
return recursion(num+1,largest,result)
|
|
|
|
|
else:
|
|
|
|
|
return result
|
|
|
|
|
return recursion(n,largest,result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
n = 2
|
|
|
|
|
result = []
|
|
|
|
|
largest = pow(10,n)-1
|
|
|
|
|
re = numbersByRecursion(1, largest, result)
|
|
|
|
|
print (re)
|
|
|
|
|
```
|
|
|
|
|
# 18.1 在 O(1) 时间内删除链表节点
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
① 如果该节点不是尾节点,那么可以直接将下一个节点的值赋给该节点,然后令该节点指向下下个节点,再删除下一个节点,时间复杂度为 O(1)。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//27ff9548-edb6-4465-92c8-7e6386e0b185.png" width="600"/> </div><br>
|
|
|
|
|
|
|
|
|
|
② 否则,就需要先遍历链表,找到节点的前一个节点,然后让前一个节点指向 null,时间复杂度为 O(N)。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//280f7728-594f-4811-a03a-fa8d32c013da.png" width="600"/> </div><br>
|
|
|
|
|
|
|
|
|
|
综上,如果进行 N 次操作,那么大约需要操作节点的次数为 N-1+N=2N-1,其中 N-1 表示 N-1 个不是尾节点的每个节点以 O(1) 的时间复杂度操作节点的总次数,N 表示 1 个尾节点以 O(N) 的时间复杂度操作节点的总次数。(2N-1)/N \~ 2,因此该算法的平均时间复杂度为 O(1)。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode deleteNode(ListNode head, ListNode tobeDelete) {
|
|
|
|
|
if (head == null || head.next == null || tobeDelete == null)
|
|
|
|
|
return null;
|
|
|
|
|
if (tobeDelete.next != null) {
|
|
|
|
|
// 要删除的节点不是尾节点
|
|
|
|
|
ListNode next = tobeDelete.next;
|
|
|
|
|
tobeDelete.val = next.val;
|
|
|
|
|
tobeDelete.next = next.next;
|
|
|
|
|
} else {
|
|
|
|
|
ListNode cur = head;
|
|
|
|
|
while (cur.next != tobeDelete)
|
|
|
|
|
cur = cur.next;
|
|
|
|
|
cur.next = null;
|
|
|
|
|
}
|
|
|
|
|
return head;
|
|
|
|
|
}
|
|
|
|
|
```
|
2018-10-08 19:50:30 +08:00
|
|
|
|
|
|
|
|
|
|
2018-09-30 21:39:11 +08:00
|
|
|
|
### 动态规划
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public int integerBreak(int n) {
|
|
|
|
|
int[] dp = new int[n + 1];
|
|
|
|
|
dp[1] = 1;
|
|
|
|
|
for (int i = 2; i <= n; i++)
|
|
|
|
|
for (int j = 1; j < i; j++)
|
|
|
|
|
dp[i] = Math.max(dp[i], Math.max(j * (i - j), dp[j] * (i - j)));
|
|
|
|
|
return dp[n];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2018-10-09 21:49:12 +08:00
|
|
|
|
```python
|
|
|
|
|
class ListNode:
|
|
|
|
|
def __init__(self, x = None):
|
|
|
|
|
self.val = x
|
|
|
|
|
self.next = None
|
|
|
|
|
def __del__(self):
|
|
|
|
|
self.val = None
|
|
|
|
|
self.next = None
|
|
|
|
|
|
|
|
|
|
class Solution:
|
|
|
|
|
def list_generate(self, lst):
|
|
|
|
|
"""
|
|
|
|
|
生成链表
|
|
|
|
|
"""
|
|
|
|
|
if not lst:
|
|
|
|
|
return None
|
|
|
|
|
list_node = ListNode()
|
|
|
|
|
list_node.value = lst[0]
|
|
|
|
|
if len(lst) == 1:
|
|
|
|
|
list_node.next_node = None
|
|
|
|
|
else:
|
|
|
|
|
list_node.next_node = self.list_generate(lst[1:])
|
|
|
|
|
return list_node
|
|
|
|
|
|
|
|
|
|
def find_node(self, node, target_value):
|
|
|
|
|
"""
|
|
|
|
|
根据给定的目标值,找出指定节点的位置
|
|
|
|
|
非题目要求,只是为了测试验证
|
|
|
|
|
"""
|
|
|
|
|
if not target_value:
|
|
|
|
|
return False
|
|
|
|
|
while node:
|
|
|
|
|
if node.value == target_value:
|
|
|
|
|
return node
|
|
|
|
|
node = node.next_node
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def delete_node(self, head_node, del_node):
|
|
|
|
|
"""
|
|
|
|
|
删除指定节点
|
|
|
|
|
"""
|
|
|
|
|
if not (head_node and del_node):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if del_node.next_node:
|
|
|
|
|
# 删除的节点不是尾节点,而且不是唯一一个节点
|
|
|
|
|
del_next_node = del_node.next_node
|
|
|
|
|
del_node.value = del_next_node.value
|
|
|
|
|
del_node.next_node = del_next_node.next_node
|
|
|
|
|
del_next_node.__del__()
|
|
|
|
|
del_next_node.__del__()
|
|
|
|
|
|
|
|
|
|
elif del_node == head_node:
|
|
|
|
|
# 唯一一个节点,删除头节点
|
|
|
|
|
head_node = None
|
|
|
|
|
del_node = None
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
# 删除节点为尾节点
|
|
|
|
|
node = head_node
|
|
|
|
|
while node.next_node != del_node:
|
|
|
|
|
node = node.next_node
|
|
|
|
|
|
|
|
|
|
node.next_node = None
|
|
|
|
|
del_node = None
|
|
|
|
|
|
|
|
|
|
return head_node
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
solution = Solution()
|
|
|
|
|
head_node = solution.list_generate(['a', 'b', 'c', 'e', 'd', 'd'])
|
|
|
|
|
|
|
|
|
|
target_value = 'a'
|
|
|
|
|
target_node = solution.find_node(head_node, target_value)
|
|
|
|
|
if target_node:
|
|
|
|
|
print (target_node.value)
|
|
|
|
|
head_node = solution.delete_node(head_node, target_node)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
node = head_node
|
|
|
|
|
if node:
|
|
|
|
|
while node:
|
|
|
|
|
print (node.value)
|
|
|
|
|
node = node.next_node
|
|
|
|
|
if node:
|
|
|
|
|
print ('->')
|
|
|
|
|
else:
|
|
|
|
|
print ('wrong')
|
|
|
|
|
```
|
2018-10-10 19:09:46 +08:00
|
|
|
|
# 18.2 删除链表中重复的结点
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/fc533c45b73a41b0b44ccba763f866ef?tpId=13&tqId=11209&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//8433fbb2-c35c-45ef-831d-e3ca42aebd51.png" width="500"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题描述
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode deleteDuplication(ListNode pHead) {
|
|
|
|
|
if (pHead == null || pHead.next == null)
|
|
|
|
|
return pHead;
|
|
|
|
|
ListNode next = pHead.next;
|
|
|
|
|
if (pHead.val == next.val) {
|
|
|
|
|
while (next != null && pHead.val == next.val)
|
|
|
|
|
next = next.next;
|
|
|
|
|
return deleteDuplication(next);
|
|
|
|
|
} else {
|
|
|
|
|
pHead.next = deleteDuplication(pHead.next);
|
|
|
|
|
return pHead;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class ListNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.next = None
|
|
|
|
|
class Solution:
|
|
|
|
|
def deleteDuplication(self, pHead):
|
|
|
|
|
# write code here
|
|
|
|
|
if not pHead or not pHead.next:
|
|
|
|
|
return pHead
|
|
|
|
|
next = pHead.next
|
|
|
|
|
if pHead.val == next.val:
|
|
|
|
|
while next and pHead.val == next.val:
|
|
|
|
|
next = next.next
|
|
|
|
|
return self.deleteDuplication(next)
|
|
|
|
|
else:
|
|
|
|
|
pHead.next = self.deleteDuplication(pHead.next)
|
|
|
|
|
return pHead
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 19. 正则表达式匹配
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/45327ae22b7b413ea21df13ee7d6429c?tpId=13&tqId=11205&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
请实现一个函数用来匹配包括 '.' 和 '\*' 的正则表达式。模式中的字符 '.' 表示任意一个字符,而 '\*' 表示它前面的字符可以出现任意次(包含 0 次)。
|
|
|
|
|
|
|
|
|
|
在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串 "aaa" 与模式 "a.a" 和 "ab\*ac\*a" 匹配,但是与 "aa.a" 和 "ab\*a" 均不匹配。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
应该注意到,'.' 是用来当做一个任意字符,而 '\*' 是用来重复前面的字符。这两个的作用不同,不能把 '.' 的作用和 '\*' 进行类比,从而把它当成重复前面字符一次。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public boolean match(char[] str, char[] pattern) {
|
|
|
|
|
|
|
|
|
|
int m = str.length, n = pattern.length;
|
|
|
|
|
boolean[][] dp = new boolean[m + 1][n + 1];
|
|
|
|
|
|
|
|
|
|
dp[0][0] = true;
|
|
|
|
|
for (int i = 1; i <= n; i++)
|
|
|
|
|
if (pattern[i - 1] == '*')
|
|
|
|
|
dp[0][i] = dp[0][i - 2];
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= m; i++)
|
|
|
|
|
for (int j = 1; j <= n; j++)
|
|
|
|
|
if (str[i - 1] == pattern[j - 1] || pattern[j - 1] == '.')
|
|
|
|
|
dp[i][j] = dp[i - 1][j - 1];
|
|
|
|
|
else if (pattern[j - 1] == '*')
|
|
|
|
|
if (pattern[j - 2] == str[i - 1] || pattern[j - 2] == '.') {
|
|
|
|
|
dp[i][j] |= dp[i][j - 1]; // a* counts as single a
|
|
|
|
|
dp[i][j] |= dp[i - 1][j]; // a* counts as multiple a
|
|
|
|
|
dp[i][j] |= dp[i][j - 2]; // a* counts as empty
|
|
|
|
|
} else
|
|
|
|
|
dp[i][j] = dp[i][j - 2]; // a* only counts as empty
|
|
|
|
|
|
|
|
|
|
return dp[m][n];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
# s, pattern都是字符串
|
|
|
|
|
def match(self, s, pattern):
|
|
|
|
|
# write code here
|
|
|
|
|
if (len(s) == 0 and len(pattern) == 0):
|
|
|
|
|
return True
|
|
|
|
|
if (len(s) > 0 and len(pattern) == 0):
|
|
|
|
|
return False
|
|
|
|
|
if (len(pattern) > 1 and pattern[1] == '*'):
|
|
|
|
|
if (len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.')):
|
|
|
|
|
return (self.match(s, pattern[2:]) or self.match(s[1:], pattern[2:]) or self.match(s[1:], pattern))
|
|
|
|
|
else:
|
|
|
|
|
return self.match(s, pattern[2:])
|
|
|
|
|
if (len(s) > 0 and (pattern[0] == '.' or pattern[0] == s[0])):
|
|
|
|
|
return self.match(s[1:], pattern[1:])
|
|
|
|
|
return False
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
import re
|
|
|
|
|
class Solution:
|
|
|
|
|
# s, pattern都是字符串
|
|
|
|
|
def match(self, s, pattern):
|
|
|
|
|
# write code here
|
|
|
|
|
if s == None or pattern == None:
|
|
|
|
|
return False
|
|
|
|
|
if s == "" and pattern == "":
|
|
|
|
|
return True
|
|
|
|
|
if pattern == "" and s != "":
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
res = re.compile(str(pattern)+"$")
|
|
|
|
|
result = res.match(str(s))
|
|
|
|
|
|
|
|
|
|
if result is None:
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
return True
|
|
|
|
|
```
|
2018-10-11 19:37:29 +08:00
|
|
|
|
# 20. 表示数值的字符串
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/6f8c901d091949a5837e24bb82a731f2?tpId=13&tqId=11206&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
true
|
|
|
|
|
|
|
|
|
|
"+100"
|
|
|
|
|
"5e2"
|
|
|
|
|
"-123"
|
|
|
|
|
"3.1416"
|
|
|
|
|
"-1E-16"
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
|
|
|
|
|
"12e"
|
|
|
|
|
"1a3.14"
|
|
|
|
|
"1.2.3"
|
|
|
|
|
"+-5"
|
|
|
|
|
"12e+4.3"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
使用正则表达式进行匹配。
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
[] : 字符集合
|
|
|
|
|
() : 分组
|
|
|
|
|
? : 重复 0 ~ 1
|
|
|
|
|
+ : 重复 1 ~ n
|
|
|
|
|
* : 重复 0 ~ n
|
|
|
|
|
. : 任意字符
|
|
|
|
|
\\. : 转义后的 .
|
|
|
|
|
\\d : 数字
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public boolean isNumeric(char[] str) {
|
|
|
|
|
if (str == null || str.length == 0)
|
|
|
|
|
return false;
|
|
|
|
|
return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?");
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
import re
|
|
|
|
|
class Solution:
|
|
|
|
|
# s字符串
|
|
|
|
|
def isNumeric(self, s):
|
|
|
|
|
# write code here
|
|
|
|
|
return re.match('[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?$', s)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 21. 调整数组顺序使奇数位于偶数前面
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/beb5aa231adc45b2a5dcc5b62c93f593?tpId=13&tqId=11166&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
需要保证奇数和奇数,偶数和偶数之间的相对位置不变,这和书本不太一样。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public void reOrderArray(int[] nums) {
|
|
|
|
|
// 奇数个数
|
|
|
|
|
int oddCnt = 0;
|
|
|
|
|
for (int val : nums)
|
|
|
|
|
if (val % 2 == 1)
|
|
|
|
|
oddCnt++;
|
|
|
|
|
int[] copy = nums.clone();
|
|
|
|
|
int i = 0, j = oddCnt;
|
|
|
|
|
for (int num : copy) {
|
|
|
|
|
if (num % 2 == 1)
|
|
|
|
|
nums[i++] = num;
|
|
|
|
|
else
|
|
|
|
|
nums[j++] = num;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
import copy
|
|
|
|
|
|
|
|
|
|
class Solution:
|
|
|
|
|
def reOrderArray(self, array):
|
|
|
|
|
# write code here
|
|
|
|
|
oddCnt = 0
|
|
|
|
|
for val in array:
|
|
|
|
|
if val % 2 == 1:
|
|
|
|
|
oddCnt += 1
|
|
|
|
|
copyArray = copy.deepcopy(array)
|
|
|
|
|
i, j = 0, oddCnt
|
|
|
|
|
for num in array:
|
|
|
|
|
if num % 2 ==1:
|
|
|
|
|
copyArray[i] = num
|
|
|
|
|
i += 1
|
|
|
|
|
else:
|
|
|
|
|
copyArray[j] = num
|
|
|
|
|
j += 1
|
|
|
|
|
return copyArray
|
|
|
|
|
```
|
|
|
|
|
|
2018-10-11 19:59:53 +08:00
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def reOrderArray(self, array):
|
|
|
|
|
# write code here
|
|
|
|
|
odd = [x for x in array if x%2]
|
|
|
|
|
even = [x for x in array if not (x%2)]
|
|
|
|
|
result = odd + even
|
|
|
|
|
return result
|
|
|
|
|
```
|
2018-10-12 20:24:45 +08:00
|
|
|
|
# 22. 链表中倒数第 K 个结点
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/529d3ae5a407492994ad2a246518148a?tpId=13&tqId=11167&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
设链表的长度为 N。设两个指针 P1 和 P2,先让 P1 移动 K 个节点,则还有 N - K 个节点可以移动。此时让 P1 和 P2 同时移动,可以知道当 P1 移动到链表结尾时,P2 移动到 N - K 个节点处,该位置就是倒数第 K 个节点。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//ea2304ce-268b-4238-9486-4d8f8aea8ca4.png" width="500"/> </div><br>
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode FindKthToTail(ListNode head, int k) {
|
|
|
|
|
if (head == null)
|
|
|
|
|
return null;
|
|
|
|
|
ListNode P1 = head;
|
|
|
|
|
while (P1 != null && k-- > 0)
|
|
|
|
|
P1 = P1.next;
|
|
|
|
|
if (k > 0)
|
|
|
|
|
return null;
|
|
|
|
|
ListNode P2 = head;
|
|
|
|
|
while (P1 != null) {
|
|
|
|
|
P1 = P1.next;
|
|
|
|
|
P2 = P2.next;
|
|
|
|
|
}
|
|
|
|
|
return P2;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
class Solution:
|
|
|
|
|
def FindKthToTail(self, head, k):
|
|
|
|
|
# write code here
|
|
|
|
|
if head == None:
|
|
|
|
|
return None
|
|
|
|
|
p1 = head
|
|
|
|
|
while p1 and k > 0:
|
|
|
|
|
k -= 1
|
|
|
|
|
p1 = p1.next
|
|
|
|
|
if k > 0:
|
|
|
|
|
return None
|
|
|
|
|
p2 = head
|
|
|
|
|
while p1:
|
|
|
|
|
p1 = p1.next
|
|
|
|
|
p2 = p2.next
|
|
|
|
|
return p2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 23. 链表中环的入口结点
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/253d2c59ec3e4bc68da16833f79a38e4?tpId=13&tqId=11208&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
一个链表中包含环,请找出该链表的环的入口结点。要求不能使用额外的空间。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 y6 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。
|
|
|
|
|
|
|
|
|
|
在相遇点,slow 要到环的入口点还需要移动 z 个节点,如果让 fast 重新从头开始移动,并且速度变为每次移动一个节点,那么它到环入口点还需要移动 x 个节点。在上面已经推导出 x=z,因此 fast 和 slow 将在环入口点相遇。
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//70fa1f83-dae7-456d-b94b-ce28963b2ba1.png"/> </div><br>
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode EntryNodeOfLoop(ListNode pHead) {
|
|
|
|
|
if (pHead == null || pHead.next == null)
|
|
|
|
|
return null;
|
|
|
|
|
ListNode slow = pHead, fast = pHead;
|
|
|
|
|
do {
|
|
|
|
|
fast = fast.next.next;
|
|
|
|
|
slow = slow.next;
|
|
|
|
|
} while (slow != fast);
|
|
|
|
|
fast = pHead;
|
|
|
|
|
while (slow != fast) {
|
|
|
|
|
slow = slow.next;
|
|
|
|
|
fast = fast.next;
|
|
|
|
|
}
|
|
|
|
|
return slow;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
class Solution:
|
|
|
|
|
def EntryNodeOfLoop(self, pHead):
|
|
|
|
|
# write code here
|
|
|
|
|
if not pHead:
|
|
|
|
|
return None
|
|
|
|
|
plist = []
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
plist.append(pHead)
|
|
|
|
|
pHead = pHead.next
|
|
|
|
|
if not pHead:
|
|
|
|
|
return None
|
|
|
|
|
if pHead in plist:
|
|
|
|
|
return pHead
|
|
|
|
|
```
|
2018-10-15 20:02:45 +08:00
|
|
|
|
# 24. 反转链表
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca?tpId=13&tqId=11168&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
### 递归
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode ReverseList(ListNode head) {
|
|
|
|
|
if (head == null || head.next == null)
|
|
|
|
|
return head;
|
|
|
|
|
ListNode next = head.next;
|
|
|
|
|
head.next = null;
|
|
|
|
|
ListNode newHead = ReverseList(next);
|
|
|
|
|
next.next = head;
|
|
|
|
|
return newHead;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class ListNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.next = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回ListNode
|
|
|
|
|
def ReverseList(self, pHead):
|
|
|
|
|
# write code here
|
|
|
|
|
if pHead == None or pHead.next == None:
|
|
|
|
|
return pHead
|
|
|
|
|
next = pHead.next
|
|
|
|
|
pHead.next = None
|
|
|
|
|
newHead = self.ReverseList(next)
|
|
|
|
|
next.next = pHead
|
|
|
|
|
return newHead
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 迭代
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode ReverseList(ListNode head) {
|
|
|
|
|
ListNode newList = new ListNode(-1);
|
|
|
|
|
while (head != null) {
|
|
|
|
|
ListNode next = head.next;
|
|
|
|
|
head.next = newList.next;
|
|
|
|
|
newList.next = head;
|
|
|
|
|
head = next;
|
|
|
|
|
}
|
|
|
|
|
return newList.next;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class ListNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.next = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回ListNode
|
|
|
|
|
def ReverseList(self, pHead):
|
|
|
|
|
# write code here
|
|
|
|
|
newList = ListNode(-1)
|
|
|
|
|
while pHead:
|
|
|
|
|
next = pHead.next
|
|
|
|
|
pHead.next = newList.next
|
|
|
|
|
newList.next = pHead
|
|
|
|
|
pHead = next
|
|
|
|
|
return newList.next
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 25. 合并两个排序的链表
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/d8b6b4358f774294a89de2a6ac4d9337?tpId=13&tqId=11169&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//43f2cafa-3568-4a89-a895-4725666b94a6.png" width="500"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
### 递归
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode Merge(ListNode list1, ListNode list2) {
|
|
|
|
|
if (list1 == null)
|
|
|
|
|
return list2;
|
|
|
|
|
if (list2 == null)
|
|
|
|
|
return list1;
|
|
|
|
|
if (list1.val <= list2.val) {
|
|
|
|
|
list1.next = Merge(list1.next, list2);
|
|
|
|
|
return list1;
|
|
|
|
|
} else {
|
|
|
|
|
list2.next = Merge(list1, list2.next);
|
|
|
|
|
return list2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class ListNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.next = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回合并后列表
|
|
|
|
|
def Merge(self, pHead1, pHead2):
|
|
|
|
|
# write code here
|
|
|
|
|
if pHead1 == None:
|
|
|
|
|
return pHead2
|
|
|
|
|
if pHead2 == None:
|
|
|
|
|
return pHead1
|
|
|
|
|
if pHead1.val <= pHead2.val:
|
|
|
|
|
pHead1.next = self.Merge(pHead1.next, pHead2)
|
|
|
|
|
return pHead1
|
|
|
|
|
else:
|
|
|
|
|
pHead2.next = self.Merge(pHead1, pHead2.next)
|
|
|
|
|
return pHead2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 迭代
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ListNode Merge(ListNode list1, ListNode list2) {
|
|
|
|
|
ListNode head = new ListNode(-1);
|
|
|
|
|
ListNode cur = head;
|
|
|
|
|
while (list1 != null && list2 != null) {
|
|
|
|
|
if (list1.val <= list2.val) {
|
|
|
|
|
cur.next = list1;
|
|
|
|
|
list1 = list1.next;
|
|
|
|
|
} else {
|
|
|
|
|
cur.next = list2;
|
|
|
|
|
list2 = list2.next;
|
|
|
|
|
}
|
|
|
|
|
cur = cur.next;
|
|
|
|
|
}
|
|
|
|
|
if (list1 != null)
|
|
|
|
|
cur.next = list1;
|
|
|
|
|
if (list2 != null)
|
|
|
|
|
cur.next = list2;
|
|
|
|
|
return head.next;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class ListNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.next = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回合并后列表
|
|
|
|
|
def Merge(self, pHead1, pHead2):
|
|
|
|
|
# write code here
|
|
|
|
|
head = ListNode(-1)
|
|
|
|
|
cur = head
|
|
|
|
|
while pHead1 and pHead2:
|
|
|
|
|
if pHead1.val <= pHead2.val:
|
|
|
|
|
cur.next = pHead1
|
|
|
|
|
pHead1 = pHead1.next
|
|
|
|
|
else:
|
|
|
|
|
cur.next = pHead2
|
|
|
|
|
pHead2 = pHead2.next
|
|
|
|
|
cur = cur.next
|
|
|
|
|
if pHead1:
|
|
|
|
|
cur.next = pHead1
|
|
|
|
|
if pHead2:
|
|
|
|
|
cur.next = pHead2
|
|
|
|
|
return head.next
|
|
|
|
|
```
|
2018-10-16 14:55:47 +08:00
|
|
|
|
# 26. 树的子结构
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/6e196c44c7004d15b1610b9afca8bd88?tpId=13&tqId=11170&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//4583e24f-424b-4d50-8a14-2c38a1827d4a.png" width="500"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
|
|
|
|
|
if (root1 == null || root2 == null)
|
|
|
|
|
return false;
|
|
|
|
|
return isSubtreeWithRoot(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean isSubtreeWithRoot(TreeNode root1, TreeNode root2) {
|
|
|
|
|
if (root2 == null)
|
|
|
|
|
return true;
|
|
|
|
|
if (root1 == null)
|
|
|
|
|
return false;
|
|
|
|
|
if (root1.val != root2.val)
|
|
|
|
|
return false;
|
|
|
|
|
return isSubtreeWithRoot(root1.left, root2.left) && isSubtreeWithRoot(root1.right, root2.right);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class TreeNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.left = None
|
|
|
|
|
# self.right = None
|
|
|
|
|
class Solution:
|
|
|
|
|
def HasSubtree(self, pRoot1, pRoot2):
|
|
|
|
|
# write code here
|
|
|
|
|
if pRoot1 == None or pRoot2 == None:
|
|
|
|
|
return False
|
|
|
|
|
return self.isSubtreeWithRoot(pRoot1, pRoot2) or \
|
|
|
|
|
self.HasSubtree(pRoot1.left, pRoot2) or \
|
|
|
|
|
self.HasSubtree(pRoot1.right, pRoot2)
|
|
|
|
|
|
|
|
|
|
def isSubtreeWithRoot(self, pRoot1, pRoot2):
|
|
|
|
|
if pRoot2 == None:
|
|
|
|
|
return True
|
|
|
|
|
if pRoot1 == None:
|
|
|
|
|
return False
|
|
|
|
|
if pRoot1.val != pRoot2.val:
|
|
|
|
|
return False
|
|
|
|
|
return self.isSubtreeWithRoot(pRoot1.left, pRoot2.left) and \
|
|
|
|
|
self.isSubtreeWithRoot(pRoot1.right, pRoot2.right)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 27. 二叉树的镜像
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/564f4c26aa584921bc75623e48ca3011?tpId=13&tqId=11171&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//a2d13178-f1ef-4811-a240-1fe95b55b1eb.png" width="300"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public void Mirror(TreeNode root) {
|
|
|
|
|
if (root == null)
|
|
|
|
|
return;
|
|
|
|
|
swap(root);
|
|
|
|
|
Mirror(root.left);
|
|
|
|
|
Mirror(root.right);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void swap(TreeNode root) {
|
|
|
|
|
TreeNode t = root.left;
|
|
|
|
|
root.left = root.right;
|
|
|
|
|
root.right = t;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class TreeNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.left = None
|
|
|
|
|
# self.right = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回镜像树的根节点
|
|
|
|
|
def Mirror(self, root):
|
|
|
|
|
# write code here
|
|
|
|
|
if root == None:
|
|
|
|
|
return
|
|
|
|
|
self.swap(root)
|
|
|
|
|
self.Mirror(root.left)
|
|
|
|
|
self.Mirror(root.right)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def swap(self, root):
|
|
|
|
|
root.left, root.right = root.right, root.left
|
|
|
|
|
```
|
2018-10-17 19:48:49 +08:00
|
|
|
|
# 28 对称的二叉树
|
|
|
|
|
|
|
|
|
|
[NowCder](https://www.nowcoder.com/practice/ff05d44dfdb04e1d83bdbdab320efbcb?tpId=13&tqId=11211&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//f42443e0-208d-41ea-be44-c7fd97d2e3bf.png" width="300"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
boolean isSymmetrical(TreeNode pRoot) {
|
|
|
|
|
if (pRoot == null)
|
|
|
|
|
return true;
|
|
|
|
|
return isSymmetrical(pRoot.left, pRoot.right);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean isSymmetrical(TreeNode t1, TreeNode t2) {
|
|
|
|
|
if (t1 == null && t2 == null)
|
|
|
|
|
return true;
|
|
|
|
|
if (t1 == null || t2 == null)
|
|
|
|
|
return false;
|
|
|
|
|
if (t1.val != t2.val)
|
|
|
|
|
return false;
|
|
|
|
|
return isSymmetrical(t1.left, t2.right) && isSymmetrical(t1.right, t2.left);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class TreeNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.left = None
|
|
|
|
|
# self.right = None
|
|
|
|
|
class Solution:
|
|
|
|
|
def isSymmetrical(self, pRoot):
|
|
|
|
|
# write code here
|
|
|
|
|
if pRoot == None:
|
|
|
|
|
return True
|
|
|
|
|
return self._isSymmetrical(pRoot.left, pRoot.right)
|
|
|
|
|
|
|
|
|
|
def _isSymmetrical(self, t1, t2):
|
|
|
|
|
if t1 == None and t2 == None:
|
|
|
|
|
return True
|
|
|
|
|
if t1 == None or t2 == None:
|
|
|
|
|
return False
|
|
|
|
|
if t1.val != t2.val:
|
|
|
|
|
return False
|
|
|
|
|
return self._isSymmetrical(t1.left, t2.right) and self._isSymmetrical(t1.right, t2.left)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 29. 顺时针打印矩阵
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/9b4c81a02cd34f76be2659fa0d54342a?tpId=13&tqId=11172&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
下图的矩阵顺时针打印结果为:1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//6539b9a4-2b24-4d10-8c94-2eb5aba1e296.png" width="300"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ArrayList<Integer> printMatrix(int[][] matrix) {
|
|
|
|
|
ArrayList<Integer> ret = new ArrayList<>();
|
|
|
|
|
int r1 = 0, r2 = matrix.length - 1, c1 = 0, c2 = matrix[0].length - 1;
|
|
|
|
|
while (r1 <= r2 && c1 <= c2) {
|
|
|
|
|
for (int i = c1; i <= c2; i++)
|
|
|
|
|
ret.add(matrix[r1][i]);
|
|
|
|
|
for (int i = r1 + 1; i <= r2; i++)
|
|
|
|
|
ret.add(matrix[i][c2]);
|
|
|
|
|
if (r1 != r2)
|
|
|
|
|
for (int i = c2 - 1; i >= c1; i--)
|
|
|
|
|
ret.add(matrix[r2][i]);
|
|
|
|
|
if (c1 != c2)
|
|
|
|
|
for (int i = r2 - 1; i > r1; i--)
|
|
|
|
|
ret.add(matrix[i][c1]);
|
|
|
|
|
r1++; r2--; c1++; c2--;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
# matrix类型为二维列表,需要返回列表
|
|
|
|
|
def printMatrix(self, matrix):
|
|
|
|
|
# write code here
|
|
|
|
|
len_row = len(matrix)
|
|
|
|
|
len_column = len(matrix[0])
|
|
|
|
|
print_list = []
|
|
|
|
|
if(len_row == 0):
|
|
|
|
|
return print_list
|
|
|
|
|
for i in range(0,(min(len_row,len_column)-1)/2+1):#圈数
|
|
|
|
|
#四条边打印+终止检测
|
|
|
|
|
#注意打印个数处理即可
|
|
|
|
|
for j in range(i,len_column-i):
|
|
|
|
|
print_list.append(matrix[i][j])
|
|
|
|
|
for j in range(i+1,len_row-i):
|
|
|
|
|
print_list.append(matrix[j][len_column-i-1])
|
|
|
|
|
if (len_row-1-i == i):
|
|
|
|
|
return print_list
|
|
|
|
|
for j in range(i+1,len_column-i):
|
|
|
|
|
print_list.append(matrix[len_row-i-1][len_column-j-1])
|
|
|
|
|
if (len_column-1-i == i):
|
|
|
|
|
return print_list
|
|
|
|
|
for j in range(i+1,len_row-i-1):
|
|
|
|
|
print_list.append(matrix[len_row-j-1][i])
|
|
|
|
|
return print_list
|
|
|
|
|
```
|
2018-09-30 21:39:11 +08:00
|
|
|
|
|
2018-10-18 19:46:55 +08:00
|
|
|
|
# 30. 包含 min 函数的栈
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/4c776177d2c04c2494f2555c9fcc1e49?tpId=13&tqId=11173&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的 min 函数。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
private Stack<Integer> dataStack = new Stack<>();
|
|
|
|
|
private Stack<Integer> minStack = new Stack<>();
|
|
|
|
|
|
|
|
|
|
public void push(int node) {
|
|
|
|
|
dataStack.push(node);
|
|
|
|
|
minStack.push(minStack.isEmpty() ? node : Math.min(minStack.peek(), node));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void pop() {
|
|
|
|
|
dataStack.pop();
|
|
|
|
|
minStack.pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int top() {
|
|
|
|
|
return dataStack.peek();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int min() {
|
|
|
|
|
return minStack.peek();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.stack = []
|
|
|
|
|
self.min_stack = []
|
|
|
|
|
def push(self, node):
|
|
|
|
|
# write code here
|
|
|
|
|
self.stack.append(node)
|
|
|
|
|
if not self.min_stack or node <= self.min_stack[-1]:
|
|
|
|
|
self.min_stack.append(node)
|
|
|
|
|
def pop(self):
|
|
|
|
|
# write code here
|
|
|
|
|
if self.stack[-1] == self.min_stack[-1]:
|
|
|
|
|
self.min_stack.pop()
|
|
|
|
|
self.stack.pop()
|
|
|
|
|
def top(self):
|
|
|
|
|
# write code here
|
|
|
|
|
return self.stack[-1]
|
|
|
|
|
def min(self):
|
|
|
|
|
# write code here
|
|
|
|
|
return self.min_stack[-1]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 31. 栈的压入、弹出序列
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&tqId=11174&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。
|
|
|
|
|
|
|
|
|
|
例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1 是该压栈序列对应的一个弹出序列,但 4,3,5,1,2 就不可能是该压栈序列的弹出序列。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
使用一个栈来模拟压入弹出操作。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public boolean IsPopOrder(int[] pushSequence, int[] popSequence) {
|
|
|
|
|
int n = pushSequence.length;
|
|
|
|
|
Stack<Integer> stack = new Stack<>();
|
|
|
|
|
for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) {
|
|
|
|
|
stack.push(pushSequence[pushIndex]);
|
|
|
|
|
while (popIndex < n && !stack.isEmpty()
|
|
|
|
|
&& stack.peek() == popSequence[popIndex]) {
|
|
|
|
|
stack.pop();
|
|
|
|
|
popIndex++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return stack.isEmpty();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
class Solution:
|
|
|
|
|
def IsPopOrder(self, pushV, popV):
|
|
|
|
|
# write code here
|
|
|
|
|
if not pushV or len(pushV)!=len(popV):
|
|
|
|
|
return False
|
|
|
|
|
stack=[]
|
|
|
|
|
for i in pushV:
|
|
|
|
|
stack.append(i)
|
|
|
|
|
while len(stack) and stack[-1]==popV[0]:
|
|
|
|
|
stack.pop()
|
|
|
|
|
popV.pop(0)
|
|
|
|
|
if len(stack):
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
```
|
2018-10-20 19:38:38 +08:00
|
|
|
|
# 32.1 从上往下打印二叉树
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/7fe2212963db4790b57431d9ed259701?tpId=13&tqId=11175&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
|
|
|
|
|
|
|
|
|
|
例如,以下二叉树层次遍历的结果为:1,2,3,4,5,6,7
|
|
|
|
|
|
|
|
|
|
<div align="center"> <img src="../pics//348bc2db-582e-4aca-9f88-38c40e9a0e69.png" width="250"/> </div><br>
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
使用队列来进行层次遍历。
|
|
|
|
|
|
|
|
|
|
不需要使用两个队列分别存储当前层的节点和下一层的节点,因为在开始遍历一层的节点时,当前队列中的节点数就是当前层的节点数,只要控制遍历这么多节点数,就能保证这次遍历的都是当前层的节点。
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
|
|
|
|
|
Queue<TreeNode> queue = new LinkedList<>();
|
|
|
|
|
ArrayList<Integer> ret = new ArrayList<>();
|
|
|
|
|
queue.add(root);
|
|
|
|
|
while (!queue.isEmpty()) {
|
|
|
|
|
int cnt = queue.size();
|
|
|
|
|
while (cnt-- > 0) {
|
|
|
|
|
TreeNode t = queue.poll();
|
|
|
|
|
if (t == null)
|
|
|
|
|
continue;
|
|
|
|
|
ret.add(t.val);
|
|
|
|
|
queue.add(t.left);
|
|
|
|
|
queue.add(t.right);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class TreeNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.left = None
|
|
|
|
|
# self.right = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回从上到下每个节点值列表,例:[1,2,3]
|
|
|
|
|
def PrintFromTopToBottom(self, root):
|
|
|
|
|
# write code here
|
|
|
|
|
queue = []
|
|
|
|
|
ret = []
|
|
|
|
|
queue.append(root)
|
|
|
|
|
while queue:
|
|
|
|
|
cnt = len(queue)
|
|
|
|
|
while cnt > 0:
|
|
|
|
|
cnt -= 1
|
|
|
|
|
t = queue.pop(0)
|
|
|
|
|
if t == None:
|
|
|
|
|
continue
|
|
|
|
|
ret.append(t.val)
|
|
|
|
|
queue.append(t.left)
|
|
|
|
|
queue.append(t.right)
|
|
|
|
|
return ret
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class TreeNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.left = None
|
|
|
|
|
# self.right = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回从上到下每个节点值列表,例:[1,2,3]
|
|
|
|
|
def PrintFromTopToBottom(self, root):
|
|
|
|
|
# write code here
|
|
|
|
|
l=[]
|
|
|
|
|
if not root:
|
|
|
|
|
return []
|
|
|
|
|
q=[root]
|
|
|
|
|
while len(q):
|
|
|
|
|
t=q.pop(0)
|
|
|
|
|
l.append(t.val)
|
|
|
|
|
if t.left:
|
|
|
|
|
q.append(t.left)
|
|
|
|
|
if t.right:
|
|
|
|
|
q.append(t.right)
|
|
|
|
|
return l
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 32.2 把二叉树打印成多行
|
|
|
|
|
|
|
|
|
|
[NowCoder](https://www.nowcoder.com/practice/445c44d982d04483b04a54f298796288?tpId=13&tqId=11213&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
|
|
|
|
|
|
|
|
|
|
## 题目描述
|
|
|
|
|
|
|
|
|
|
和上题几乎一样。
|
|
|
|
|
|
|
|
|
|
## 解题思路
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
|
|
|
|
|
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
|
|
|
|
|
Queue<TreeNode> queue = new LinkedList<>();
|
|
|
|
|
queue.add(pRoot);
|
|
|
|
|
while (!queue.isEmpty()) {
|
|
|
|
|
ArrayList<Integer> list = new ArrayList<>();
|
|
|
|
|
int cnt = queue.size();
|
|
|
|
|
while (cnt-- > 0) {
|
|
|
|
|
TreeNode node = queue.poll();
|
|
|
|
|
if (node == null)
|
|
|
|
|
continue;
|
|
|
|
|
list.add(node.val);
|
|
|
|
|
queue.add(node.left);
|
|
|
|
|
queue.add(node.right);
|
|
|
|
|
}
|
|
|
|
|
if (list.size() != 0)
|
|
|
|
|
ret.add(list);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# -*- coding:utf-8 -*-
|
|
|
|
|
# class TreeNode:
|
|
|
|
|
# def __init__(self, x):
|
|
|
|
|
# self.val = x
|
|
|
|
|
# self.left = None
|
|
|
|
|
# self.right = None
|
|
|
|
|
class Solution:
|
|
|
|
|
# 返回二维列表[[1,2],[4,5]]
|
|
|
|
|
def Print(self, pRoot):
|
|
|
|
|
# write code here
|
|
|
|
|
ret = []
|
|
|
|
|
# queue = []
|
|
|
|
|
# queue.append(pRoot)
|
|
|
|
|
queue = [pRoot]
|
|
|
|
|
while queue:
|
|
|
|
|
list = []
|
|
|
|
|
cnt = len(queue)
|
|
|
|
|
while cnt > 0:
|
|
|
|
|
cnt -= 1
|
|
|
|
|
node = queue.pop(0)
|
|
|
|
|
if node == None:
|
|
|
|
|
continue
|
|
|
|
|
list.append(node.val)
|
|
|
|
|
queue.append(node.left)
|
|
|
|
|
queue.append(node.right)
|
|
|
|
|
if len(list):
|
|
|
|
|
ret.append(list)
|
|
|
|
|
return ret
|
|
|
|
|
```
|
2018-10-18 19:46:55 +08:00
|
|
|
|
|
2018-09-19 10:01:05 +08:00
|
|
|
|
# 参考文献
|
|
|
|
|
|
|
|
|
|
- 何海涛. 剑指 Offer[M]. 电子工业出版社, 2012.
|