Skip to content

Commit 7808672

Browse files
committed
feat: add solutions to lcof problem: No.68
1 parent 5be8de3 commit 7808672

File tree

7 files changed

+196
-50
lines changed

7 files changed

+196
-50
lines changed

lcof/面试题65. 不用加减乘除做加法/README.md

+16-18
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828

2929
**方法一:位运算**
3030

31-
两数字 `a`,`b` 求和。
31+
两数字 $a$, $b$ 求和。
3232

33-
假设 $a_i$ 和 $b_i$ 分别表示 `a``b` 的第 $i$ 个二进制位。一共有 4 种情况:
33+
假设 $a_i$ 和 $b_i$ 分别表示 $a$ 和 $b$ 的第 $i$ 个二进制位。一共有 $4$ 种情况:
3434

3535
| $a_i$ | $b_i$ | 不进位的和 | 进位 |
3636
| ----- | ----- | ---------- | ---- |
@@ -44,7 +44,9 @@
4444
- 对两数进行按位 `&` 与运算,然后左移一位,得到进位;
4545
- 对两数进行按位 `^` 异或运算,得到不进位的和;
4646
- 问题转换为求:“不进位的数 + 进位” 之和;
47-
- 循环,直至进位为 0,返回不进位的数即可(也可以用递归实现)。
47+
- 循环,直至进位为 $0$,返回不进位的数即可(也可以用递归实现)。
48+
49+
时间复杂度 $O(\log M)$,空间复杂度 $O(1)$。其中 $M$ 为整数的最大值。
4850

4951
<!-- tabs:start -->
5052

@@ -68,8 +70,6 @@ class Solution:
6870

6971
<!-- 这里可写当前语言的特殊实现逻辑 -->
7072

71-
迭代:
72-
7373
```java
7474
class Solution {
7575
public int add(int a, int b) {
@@ -83,8 +83,6 @@ class Solution {
8383
}
8484
```
8585

86-
递归:
87-
8886
```java
8987
class Solution {
9088
public int add(int a, int b) {
@@ -112,6 +110,17 @@ public:
112110
};
113111
```
114112
113+
### **Go**
114+
115+
```go
116+
func add(a int, b int) int {
117+
if b == 0 {
118+
return a
119+
}
120+
return add(a^b, (a&b)<<1)
121+
}
122+
```
123+
115124
### **JavaScript**
116125

117126
```js
@@ -128,17 +137,6 @@ var add = function (a, b) {
128137
};
129138
```
130139

131-
### **Go**
132-
133-
```go
134-
func add(a int, b int) int {
135-
if b == 0 {
136-
return a
137-
}
138-
return add(a^b, (a&b)<<1)
139-
}
140-
```
141-
142140
### **C#**
143141

144142
```cs

lcof/面试题68 - I. 二叉搜索树的最近公共祖先/README.md

+128-19
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,18 @@
4242

4343
<!-- 这里可写通用的实现逻辑 -->
4444

45-
从上到下搜索,找到第一个值位于 `[p, q]` 之间的结点即可。既可以用迭代实现,也可以用递归实现。
45+
**方法一:一次遍历**
46+
47+
从上到下遍历二叉树,找到第一个值位于 $[p.val,.. q.val]$ 之间的结点即可。既可以用迭代实现,也可以用递归实现。
48+
49+
时间复杂度 $O(n)$,其中 $n$ 是二叉树的结点数。空间复杂度方面,迭代实现的空间复杂度为 $O(1)$,递归实现的空间复杂度为 $O(n)$。
4650

4751
<!-- tabs:start -->
4852

4953
### **Python3**
5054

5155
<!-- 这里可写当前语言的特殊实现逻辑 -->
5256

53-
#### 迭代法
54-
5557
```python
5658
# Definition for a binary tree node.
5759
# class TreeNode:
@@ -65,9 +67,7 @@ class Solution:
6567
def lowestCommonAncestor(
6668
self, root: TreeNode, p: TreeNode, q: TreeNode
6769
) -> TreeNode:
68-
if p == q:
69-
return p
70-
while root:
70+
while 1:
7171
if root.val < p.val and root.val < q.val:
7272
root = root.right
7373
elif root.val > p.val and root.val > q.val:
@@ -76,8 +76,6 @@ class Solution:
7676
return root
7777
```
7878

79-
#### 递归法
80-
8179
```python
8280
# Definition for a binary tree node.
8381
# class TreeNode:
@@ -111,10 +109,7 @@ class Solution:
111109
*/
112110
class Solution {
113111
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
114-
if (p == q) {
115-
return p;
116-
}
117-
while (root != null) {
112+
while (true) {
118113
if (root.val < p.val && root.val < q.val) {
119114
root = root.right;
120115
} else if (root.val > p.val && root.val > q.val) {
@@ -123,11 +118,131 @@ class Solution {
123118
return root;
124119
}
125120
}
126-
return null;
127121
}
128122
}
129123
```
130124

125+
```java
126+
/**
127+
* Definition for a binary tree node.
128+
* public class TreeNode {
129+
* int val;
130+
* TreeNode left;
131+
* TreeNode right;
132+
* TreeNode(int x) { val = x; }
133+
* }
134+
*/
135+
class Solution {
136+
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
137+
if (root.val < p.val && root.val < q.val) {
138+
return lowestCommonAncestor(root.right, p, q);
139+
}
140+
if (root.val > p.val && root.val > q.val) {
141+
return lowestCommonAncestor(root.left, p, q);
142+
}
143+
return root;
144+
}
145+
}
146+
```
147+
148+
### **C++**
149+
150+
```cpp
151+
/**
152+
* Definition for a binary tree node.
153+
* struct TreeNode {
154+
* int val;
155+
* TreeNode *left;
156+
* TreeNode *right;
157+
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
158+
* };
159+
*/
160+
class Solution {
161+
public:
162+
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
163+
if (root->val < p->val && root->val < q->val) {
164+
return lowestCommonAncestor(root->right, p, q);
165+
}
166+
if (root->val > p->val && root->val > q->val) {
167+
return lowestCommonAncestor(root->left, p, q);
168+
}
169+
return root;
170+
}
171+
};
172+
```
173+
174+
```cpp
175+
/**
176+
* Definition for a binary tree node.
177+
* struct TreeNode {
178+
* int val;
179+
* TreeNode *left;
180+
* TreeNode *right;
181+
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
182+
* };
183+
*/
184+
class Solution {
185+
public:
186+
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
187+
while (1) {
188+
if (root->val < p->val && root->val < q->val) {
189+
root = root->right;
190+
} else if (root->val > p->val && root->val > q->val) {
191+
root = root->left;
192+
} else {
193+
return root;
194+
}
195+
}
196+
}
197+
};
198+
```
199+
200+
### **Go**
201+
202+
```go
203+
/**
204+
* Definition for a binary tree node.
205+
* type TreeNode struct {
206+
* Val int
207+
* Left *TreeNode
208+
* Right *TreeNode
209+
* }
210+
*/
211+
212+
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
213+
if root.Val < p.Val && root.Val < q.Val {
214+
return lowestCommonAncestor(root.Right, p, q)
215+
}
216+
if root.Val > p.Val && root.Val > q.Val {
217+
return lowestCommonAncestor(root.Left, p, q)
218+
}
219+
return root
220+
}
221+
```
222+
223+
```go
224+
/**
225+
* Definition for a binary tree node.
226+
* type TreeNode struct {
227+
* Val int
228+
* Left *TreeNode
229+
* Right *TreeNode
230+
* }
231+
*/
232+
233+
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
234+
for {
235+
if root.Val < p.Val && root.Val < q.Val {
236+
root = root.Right
237+
} else if root.Val > p.Val && root.Val > q.Val {
238+
root = root.Left
239+
} else {
240+
return root
241+
}
242+
}
243+
}
244+
```
245+
131246
### **JavaScript**
132247

133248
```js
@@ -145,8 +260,6 @@ class Solution {
145260
* @return {TreeNode}
146261
*/
147262
var lowestCommonAncestor = function (root, p, q) {
148-
// 递归
149-
if (!root) return null;
150263
if (root.val < p.val && root.val < q.val) {
151264
return lowestCommonAncestor(root.right, p, q);
152265
} else if (root.val > p.val && root.val > q.val) {
@@ -158,8 +271,6 @@ var lowestCommonAncestor = function (root, p, q) {
158271

159272
### **TypeScript**
160273

161-
递归:
162-
163274
```ts
164275
/**
165276
* Definition for a binary tree node.
@@ -192,8 +303,6 @@ function lowestCommonAncestor(
192303
}
193304
```
194305

195-
循环:
196-
197306
```ts
198307
/**
199308
* Definition for a binary tree node.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* struct TreeNode {
4+
* int val;
5+
* TreeNode *left;
6+
* TreeNode *right;
7+
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
8+
* };
9+
*/
10+
class Solution {
11+
public:
12+
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
13+
if (root->val < p->val && root->val < q->val) {
14+
return lowestCommonAncestor(root->right, p, q);
15+
}
16+
if (root->val > p->val && root->val > q->val) {
17+
return lowestCommonAncestor(root->left, p, q);
18+
}
19+
return root;
20+
}
21+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* type TreeNode struct {
4+
* Val int
5+
* Left *TreeNode
6+
* Right *TreeNode
7+
* }
8+
*/
9+
10+
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
11+
if root.Val < p.Val && root.Val < q.Val {
12+
return lowestCommonAncestor(root.Right, p, q)
13+
}
14+
if root.Val > p.Val && root.Val > q.Val {
15+
return lowestCommonAncestor(root.Left, p, q)
16+
}
17+
return root
18+
}

lcof/面试题68 - I. 二叉搜索树的最近公共祖先/Solution.js

-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
* @return {TreeNode}
1313
*/
1414
var lowestCommonAncestor = function (root, p, q) {
15-
// 递归
16-
if (!root) return null;
1715
if (root.val < p.val && root.val < q.val) {
1816
return lowestCommonAncestor(root.right, p, q);
1917
} else if (root.val > p.val && root.val > q.val) {

lcof/面试题68 - I. 二叉搜索树的最近公共祖先/Solution.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ class Solution:
1010
def lowestCommonAncestor(
1111
self, root: TreeNode, p: TreeNode, q: TreeNode
1212
) -> TreeNode:
13-
if p == q:
14-
return p
15-
while root:
13+
while 1:
1614
if root.val < p.val and root.val < q.val:
1715
root = root.right
1816
elif root.val > p.val and root.val > q.val:

lcof/面试题68 - II. 二叉树的最近公共祖先/README.md

+12-8
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,22 @@
4343

4444
<!-- 这里可写通用的实现逻辑 -->
4545

46-
根据“**最近公共祖先**”的定义,若 root 是 p, q 的最近公共祖先 ,则只可能为以下情况之一:
46+
**方法一:递归**
4747

48-
- 如果 p 和 q 分别是 root 的左右节点,那么 root 就是我们要找的最近公共祖先;
49-
- 如果 p 和 q 都是 root 的左节点,那么返回 `lowestCommonAncestor(root.left, p, q)`
50-
- 如果 p 和 q 都是 root 的右节点,那么返回 `lowestCommonAncestor(root.right, p, q)`
48+
根据“**最近公共祖先**”的定义,若 $root$ 是 $p$, $q$ 的最近公共祖先,则只可能为以下情况之一:
49+
50+
- 如果 $p$ 和 $q$ 分别是 $root$ 的左右节点,那么 $root$ 就是我们要找的最近公共祖先;
51+
- 如果 $p$ 和 $q$ 都是 $root$ 的左节点,那么返回 $lowestCommonAncestor(root.left, p, q)$;
52+
- 如果 $p$ 和 $q$ 都是 $root$ 的右节点,那么返回 $lowestCommonAncestor(root.right, p, q)$。
5153

5254
**边界条件讨论**
5355

54-
- 如果 root 为 null,则说明我们已经找到最底了,返回 null 表示没找到;
55-
- 如果 root 与 p 相等或者与 q 相等,则返回 root;
56-
- 如果左子树没找到,递归函数返回 null,证明 p 和 q 同在 root 的右侧,那么最终的公共祖先就是右子树找到的结点;
57-
- 如果右子树没找到,递归函数返回 null,证明 p 和 q 同在 root 的左侧,那么最终的公共祖先就是左子树找到的结点。
56+
- 如果 $root$ 为 `null`,则说明我们已经找到最底了,返回 `null` 表示没找到;
57+
- 如果 $root$ 与 $p$ 相等或者与 $q$ 相等,则返回 $root$;
58+
- 如果左子树没找到,递归函数返回 `null`,证明 $p$ 和 $q$ 同在 $root$ 的右侧,那么最终的公共祖先就是右子树找到的结点;
59+
- 如果右子树没找到,递归函数返回 `null`,证明 $p$ 和 $q$ 同在 $root$ 的左侧,那么最终的公共祖先就是左子树找到的结点。
60+
61+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。
5862

5963
<!-- tabs:start -->
6064

0 commit comments

Comments
 (0)