Skip to content

Commit e045133

Browse files
author
haoyang.shi
committed
offer two
1 parent 8c19189 commit e045133

9 files changed

Lines changed: 323 additions & 6 deletions

SUMMARY.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@
182182
- [对称二叉树](offer/IsSymmetrical.md)
183183
- [序列化二叉树](offer/SerializeTree.md)
184184
- [数据流中的中位数](offer/StreamMid.md)
185-
- [数字序列中的某一位的数字]()
186-
- [把数字翻译成字符串]()
187-
- [礼物的最大价值]()
188-
- [最长不含重复字符的子字符串]()
189-
- [在排序数组中查找数字]()
190-
- [二叉搜索树的第K大节点]()
185+
- [数字序列中的某一位的数字](offer/NOfNumberSerialize.md)
186+
- [把数字翻译成字符串](offer/TranslateNumToStr.md)
187+
- [礼物的最大价值](offer/MaxGift.md)
188+
- [最长不含重复字符的子字符串](offer/LongestNoRepeatSubString.md)
189+
- [在排序数组中查找数字](offer/CountOfSortedArray.md)
190+
- [二叉搜索树的第K大节点](offer/BSTKthNode.md)
191191
- [滑动窗口的最大值]()
192192
- [股票的最大利润]()

offer/BSTKthNode.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# 二叉搜索树的第k个结点
2+
3+
## 题目
4+
5+
6+
给定一棵二叉搜索树,请找出其中的第 k 小的结点。例如,`5,3,7,2,4,6,8` 中,按结点数值大小顺序第三小结点的值为4。
7+
8+
[牛客网](https://www.nowcoder.com/practice/ef068f602dde4d28aab2b210e859150a?tpId=13&tqId=11215&tPage=4&rp=2&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking)
9+
10+
11+
## 解题思路
12+
13+
1. BST 中序遍历的结果就是排序后的结果
14+
15+
```
16+
public TreeNode KthNode(TreeNode pRoot, int k) {
17+
TreeNode[] nodes = new TreeNode[1];
18+
19+
int[] ints = {0};
20+
21+
KthNode(pRoot, k, nodes, ints);
22+
23+
return nodes[0];
24+
}
25+
26+
private void KthNode(TreeNode root, int k, TreeNode[] res, int[] cursor) {
27+
if (root == null) return;
28+
29+
if (res[0] != null) return;
30+
31+
KthNode(root.left, k, res, cursor);
32+
cursor[0]++;
33+
34+
if (cursor[0] == k) {
35+
res[0] = root;
36+
return;
37+
}
38+
39+
KthNode(root.right, k, res, cursor);
40+
}
41+
```

offer/CountOfSortedArray.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# 在排序数组中查找数字
2+
3+
## 题目
4+
5+
统计一个数字在排序数组中出现的次数。
6+
7+
## 解题思路
8+
9+
1. 通过二分查找分别找到 n 的第一个位置和最后一个位置
10+
2. 再进行计算就可以得出结果
11+
12+
```
13+
public int countOfSortedArray2(int[] nums, int n) {
14+
if (nums == null || nums.length == 0) return 0;
15+
16+
int firstN = getFirstN(nums, n);
17+
int lastN = getLastN(nums, n);
18+
19+
return lastN - firstN + 1;
20+
}
21+
22+
private int getFirstN(int[] nums, int n) {
23+
int s = 0, e = nums.length - 1;
24+
25+
int mid = -1;
26+
while (s <= e) {
27+
mid = (s + e) / 2;
28+
29+
if (mid > 0 && nums[mid - 1] == n) {
30+
e = mid - 1;
31+
continue;
32+
}
33+
34+
if (nums[mid] > n) {
35+
e = mid - 1;
36+
continue;
37+
}
38+
39+
if (nums[mid] < n) {
40+
s = mid + 1;
41+
continue;
42+
}
43+
44+
break;
45+
}
46+
47+
return mid;
48+
}
49+
50+
private int getLastN(int[] nums, int n) {
51+
int s = 0, e = nums.length - 1;
52+
53+
int mid = -1;
54+
while (s <= e) {
55+
mid = (s + e) / 2;
56+
57+
if (mid < nums.length - 1 && nums[mid + 1] == n) {
58+
s = mid + 1;
59+
continue;
60+
}
61+
62+
if (nums[mid] > n) {
63+
e = mid - 1;
64+
continue;
65+
}
66+
67+
if (nums[mid] < n) {
68+
s = mid + 1;
69+
continue;
70+
}
71+
72+
break;
73+
}
74+
75+
return mid;
76+
}
77+
```

offer/LongestNoRepeatSubString.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# 最长不含重复字符的子字符串
2+
3+
## 题目
4+
5+
[LeetCode](https://leetcode-cn.com/explore/interview/card/bytedance/242/string/1012/)
6+
7+
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
8+
9+
```
10+
输入: "abcabcbb"
11+
输出: 3
12+
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
13+
```
14+
15+
## 解题思路
16+
17+
1. 用 Map 记录字符所在位置,当遇到重复字符时,移动 `start` 指针
18+
2. 替换 Map 中下标,并计算子串长度
19+
20+
```
21+
public int longestNoRepeatSubString(String str) {
22+
if (str == null || str.length() == 0) return 0;
23+
24+
HashMap<Character, Integer> temp = new HashMap<>();
25+
char[] chars = str.toCharArray();
26+
27+
int res = 0, start = 0;
28+
for (int i = 0; i < chars.length; i++) {
29+
if (temp.containsKey(chars[i])) {
30+
start = Math.max(temp.put(chars[i], i) + 1, start);
31+
}
32+
33+
temp.put(chars[i], i);
34+
res = Math.max(res, i - start + 1);
35+
}
36+
37+
return res;
38+
}
39+
```

offer/MaxGift.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# 礼物的最大值
2+
3+
## 题目
4+
5+
在一个 `m*n` 的棋盘中的每一个格都放一个礼物,每个礼物都有一定的价值(价值大于0).你可以从棋盘的左上角开始拿各种里的礼物,并每次向左或者向下移动一格,直到到达棋盘的右下角。给定一个棋盘及上面个的礼物,请计算你最多能拿走多少价值的礼物?
6+
7+
比如说现在有一个如下的棋盘:
8+
9+
![image](images/d59a892b85e600aecc22e2eca74d517f.png)
10+
11+
在这个棋盘中,按照`1,12,5,7,7,16,5`的顺序可以拿到总价值最大的礼物。
12+
13+
## 解题思路
14+
15+
1. 动态规划,定义 $$f(x,y)$$ 表示`x,y`点上能获取的最大数
16+
2. 状态转移方程:$$f(x,y)=\max(f(x-1,y),f(x,y-1))+g(x,y)$$
17+
3. 可以考虑使用一维数组进行记录
18+
19+
```
20+
public int maxGift(int[][] matrix) {
21+
for (int i = 0; i < matrix.length; i++) {
22+
for (int j = 0; j < matrix[i].length; j++) {
23+
int a = i > 0 ? matrix[i - 1][j] : 0;
24+
int b = j > 0 ? matrix[i][j - 1] : 0;
25+
26+
matrix[i][j] += Math.max(a, b);
27+
}
28+
}
29+
30+
System.out.println(Arrays.deepToString(matrix));
31+
32+
return matrix[matrix.length - 1][matrix[0].length - 1];
33+
}
34+
```

offer/MaxInWindows.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# 滑动窗口的最大值
2+
3+
## 题目
4+
5+
[牛客网](https://www.nowcoder.com/practice/1624bc35a45c42c0bc17d17fa0cba788?tpId=13&tqId=11217&tPage=4&rp=2&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking)
6+
7+
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组`{2,3,4,2,6,2,5,1}`及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为`{4,4,6,6,6,5}`; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: `{[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}`
8+
9+
## 解题思路
10+
11+
1. 使用一个队列来保存最大值和次大的值
12+
13+
```
14+
public ArrayList<Integer> maxInWindows(int[] num, int size) {
15+
ArrayList<Integer> res = new ArrayList<>();
16+
17+
if (size == 0) return res;
18+
19+
LinkedList<Integer> queue = new LinkedList<>();
20+
21+
for (int i = 0; i < num.length; i++) {
22+
while (queue.peekFirst() != null && i - queue.peekFirst() >= size) {
23+
queue.removeFirst();
24+
}
25+
26+
while (queue.peekLast() != null && i - queue.peekLast() >= size) {
27+
queue.removeLast();
28+
}
29+
30+
if (queue.isEmpty()) {
31+
queue.addFirst(i);
32+
} else {
33+
if (num[i] > num[queue.peekFirst()]) {
34+
queue.clear();
35+
queue.addFirst(i);
36+
} else {
37+
while (num[i] > num[queue.peekLast()]) {
38+
queue.removeLast();
39+
}
40+
queue.addLast(i);
41+
}
42+
}
43+
44+
if (i >= size - 1) res.add(num[queue.peekFirst()]);
45+
}
46+
47+
return res;
48+
}
49+
```

offer/NOfNumberSerialize.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# 数字序列中的某一位的数字
2+
3+
## 题目
4+
5+
数字以`0123456789101112131415…`的格式序列化到一个字符序列中。在这个序列中,第5位(从0开始计数,即从第0位开始)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。
6+
7+
## 解题思路
8+
9+
1. 可以将 n 进行拆分,1位数一共10个数字、10位,2位数一共90个数字、180位,依此类推
10+
2. 当确定 n 所在位数范围时,对位数取商,计算出 n 位对应的数字 a,再取余,计算出结果位于 a 的第几位
11+
12+
```
13+
public int nOfNumberSerialize(int n) {
14+
int i = 1;
15+
int count = 0;
16+
int nLeft = n;
17+
18+
while (true) {
19+
nLeft -= count;
20+
count = countOfIntegers(i) * i;
21+
22+
if (nLeft < count) {
23+
break;
24+
}
25+
26+
i++;
27+
}
28+
29+
int a = nLeft / i;
30+
String s = String.valueOf(a);
31+
32+
return s.charAt(nLeft % i) - '0';
33+
}
34+
35+
private int countOfIntegers(int n) {
36+
int sum = 0;
37+
38+
if (n == 1) {
39+
sum = 10;
40+
} else {
41+
sum = (int) (9 * Math.pow(10, n - 1));
42+
}
43+
44+
return sum;
45+
}
46+
```

offer/TranslateNumToStr.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# 把数字翻译成字符串
2+
3+
## 题目
4+
5+
给定一个数字,按照如下规则翻译成字符串:0 翻译成“a”,`1` 翻译成`“b”``25`翻译成`“z”`。一个数字有多种翻译可能,例如`12258`一共有`5`种,分别是`bccfi``bwfi``bczi``mcfi``mzi`。实现一个函数,用来计算一个数字有多少种不同的翻译方法。
6+
7+
## 解题思路
8+
9+
1. 定义 $$f(i)$$ 表示第 `i` 位有多少种翻译的方法,动态规划方程:$$f(i)=f(i+1)+g(i,i+1) \times f(i+2)$$
10+
2. 其中 $$g(i,i+1)$$ 表示 `i,i+1` 是否能组成 `10 ~ 25`
11+
12+
```
13+
public int translateNumToStr(int num) {
14+
char[] str = String.valueOf(num).toCharArray();
15+
int[] res = new int[str.length];
16+
17+
for (int i = str.length - 1; i >= 0; i--) {
18+
if (i + 1 >= str.length) {
19+
res[i] = 1;
20+
continue;
21+
}
22+
23+
res[i] = res[i + 1];
24+
25+
if (i + 2 < str.length && str[i] <= '2' && str[i] >= '1' && str[i + 1] <= '5') {
26+
res[i] += res[i + 2];
27+
}
28+
}
29+
return res[0];
30+
}
31+
```
5.19 KB
Loading

0 commit comments

Comments
 (0)