Skip to content

Commit 6e15efb

Browse files
committed
009
1 parent 100b39b commit 6e15efb

File tree

7 files changed

+192
-1
lines changed

7 files changed

+192
-1
lines changed

007-用两个栈实现队列/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
> 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
55
6-
#分析
6+
## 分析
77
始终维护s1作为存储空间,以s2作为临时缓冲区。
88

99
始终维护s1作为输入栈,以s2作为输出栈
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# 题意
2+
3+
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减序列的一个旋转,输出旋转数组的最小元素。
4+
5+
例如
6+
7+
>数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,
8+
9+
该数组的最小值为1。
10+
11+
## 解题思路
12+
13+
和二分查找法一样,用两个指针分别指向数组的第一个元素和最后一个元素。
14+
15+
我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后面子数组的元素。我们还可以注意到最小的元素刚好是这两个子数组的分界线。
16+
17+
我们试着用二元查找法的思路在寻找这个最小的元素。
18+
19+
首先我们用两个指针,分别指向数组的第一个元素和最后一个元素。按照题目旋转的规则,第一个元素应该是大于或者等于最后一个元素的(这其实不完全对,还有特例。后面再讨论特例)。
20+
21+
接着我们得到处在数组中间的元素
22+
23+
- 如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。
24+
25+
此时数组中最小的元素应该位于该中间 元素的后面。我们可以把第一指针指向该中间元素,这样可以缩小寻找的范围。
26+
27+
- 同样,如果中间元素位于后面的递增子数组,那么它应该小于或者等于第二个指针指向的元素。此时该数组中最小的元素应该位于该中间元素的前面。我们可以把第二个指针指向该中间元素,这样同样可以缩小寻找的范围。我们接着再用更新之后的 两个指针,去得到和比较新的中间元素,循环下去。
28+
29+
## 特殊
30+
31+
我们考虑下特殊情况,我们的循环判断是以rotateArray[low] >= rotateArray[high]为条件的,不满足这个的特殊情况有那些呢?
32+
33+
由于是把递增排序数组前面的若干个数据搬到后面去,因此第一个数字总是大于或者等于最后一个数字,但按照定义还有一个
34+
35+
特例:开始时就rotateArray[low] < rotateArray[high],那么循环不会执行
36+
37+
如果数组旋转后仍然有序,即rotateArray[low] < rotateArray[high]
38+
如果把排序数组前面0个元素搬到后面,也就是说其实没有旋转,
39+
40+
那么第0个元素就是最小的元素
41+
42+
因此我们将mid初始化为0
43+
44+
现在可以了么,有没有特殊情况仍然未被处理的,
45+
46+
如果rotateArray[low] = rotateArray[high]
47+
48+
> 测试用例: [1, 0, 1, 0, 1, 1]
49+
> 对应输出应该为:
50+
> 0
51+
> 你的输出为:
52+
> 1
53+
54+
此时
55+
56+
> rotateArray[low] rotateArray[mid] rotateArray[high]三者相等
57+
> 无法确定中间元素是属于前面还是后面的递增子数组
58+
> 只能顺序查找
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package problem008
2+
3+
func minNumberInRotateArray(array []int) int {
4+
low, high := 0, len(array)-1
5+
if array[low] < array[high] {
6+
return array[low]
7+
}
8+
mid := (low + high) / 2
9+
for array[low] >= array[high] {
10+
// array[low] >= array[high] 所以此时high为最小值
11+
if high-low == 1 {
12+
mid = high
13+
break
14+
}
15+
mid = (low + high) / 2
16+
17+
// array[low] array[mid] array[high]三者相等
18+
// 无法确定中间元素是属于前面还是后面的递增子数组
19+
// 只能顺序查找
20+
if array[low] == array[mid] && array[mid] == array[high] {
21+
return MinOrder(array, low, high)
22+
}
23+
24+
25+
if array[mid] >= array[low] {
26+
low = mid
27+
} else {
28+
high = mid
29+
}
30+
}
31+
return array[mid]
32+
}
33+
34+
// 顺序查找
35+
func MinOrder(array []int, low, high int) int {
36+
min := array[low]
37+
for i := low; i <= high; i++ {
38+
if array[i] < min {
39+
min = array[i]
40+
}
41+
}
42+
return min
43+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package problem008
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func Test_case1(t *testing.T) {
8+
if minNumberInRotateArray([]int{3, 4, 5, 1, 2}) == 1 {
9+
t.Log("Pass")
10+
} else {
11+
t.Error("Failed")
12+
}
13+
}
14+
15+
func Test_case2(t *testing.T) {
16+
if minNumberInRotateArray([]int{1 , 0, 1, 1, 1}) == 0 {
17+
t.Log("Pass")
18+
} else {
19+
t.Error("Failed")
20+
}
21+
}
22+
23+
func Test_case3(t *testing.T) {
24+
if minNumberInRotateArray([]int{2,2,3,4,1,1,2,2,2}) == 1 {
25+
t.Log("Pass")
26+
} else {
27+
t.Error("Failed")
28+
}
29+
}

009-斐波那契数列/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# 题意
2+
3+
大家都知道斐波那契数列, 现在要求输入一个整数n, 请你输出斐波那契数列的第n项。
4+
5+
# 递推公式
6+
7+
我们很容易的想到了递推公式
8+
9+
f(n) = 0, 当n=0
10+
f(n) = 1, 当n=1
11+
f(n) = f(n - 1) + f(n - 2), 其他
12+
13+
因此我们马上想到了递归,但是要尽量减少重复计算
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package problem009
2+
3+
func Fibonacci(n int) int {
4+
if n <= 1 {
5+
return n
6+
}
7+
f1, f2 := 0, 1
8+
res := 0
9+
for i := 2; i <= n; i++ {
10+
res = f1+f2
11+
f1, f2 = f2, res
12+
}
13+
return res
14+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package problem009
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func Test_case(t *testing.T) {
8+
if Fibonacci(0) == 0 {
9+
t.Log("Pass")
10+
} else {
11+
t.Error("Failed")
12+
}
13+
14+
if Fibonacci(1) == 1 {
15+
t.Log("Pass")
16+
} else {
17+
t.Error("Failed")
18+
}
19+
20+
if Fibonacci(7) == 13 {
21+
t.Log("Pass")
22+
} else {
23+
t.Error("Failed")
24+
}
25+
26+
27+
if Fibonacci(13) == 233 {
28+
t.Log("Pass")
29+
} else {
30+
t.Error("Failed")
31+
}
32+
33+
}
34+

0 commit comments

Comments
 (0)