数组
二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例:
1
2输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4 1
2输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
二分法的区间:区间需要遵循循环不变量原则,二分法的区间定义一般有两种:左闭右闭[left, right]和左闭右开[left, right]。
区别:
- 左闭右闭时target
可能是nums[left]
或者nums[right[
,当left = right
时,则nums[left] = nums[right] = nums[middle] = target
。所以在这种情况下left
是可以等于right
的, while(left <= right)
且:
nums[middle] > target
时 left
不变 right = middle-1
因为 nums[middle] != target
。
同理nums[middle] < target
时right
不变 left = middle +1
.
- 左闭右开时,
target
不可能等于nums[right]
, 所以while(right<left)
且:
nums[middle] > target
时left
不变right = middle
但当nums[middle] < target
时right
不变left = middle +1
.
下面是python代码: [left, right] 1
2
3
4
5
6
7
8
9
10
11
12
13def search(nums: list, target: int) -> int:
left, right = 0, len(nums) - 1
while(left <= right):
middle = (left + right) // 2
if(nums[middle] > target):
right = middle - 1
elif(nums[middle < target]):
left = middle + 1
else:
return middle
return -1 1
2
3
4
5
6
7
8
9
10
11
12
13def search(nums: list, target: int) -> int:
left, right = 0, len(nums) - 1
while(left < right):
middle = (left + right) // 2
if(nums[middle] > target):
right = middle
elif(nums[middle < target]):
left = middle + 1
else:
return middle
return -1
例子: 1
2nums = [-1,0,3,5,9,12]
search(nums, 0)1
2
3
4nums: [-1, 0, 3, 5, 9, 12]
left: 0 right: 5 middle: 2
left: 0 right: 1 middle: 0
left: 1 right: 1 middle: 11
2
3nums: [-1, 0, 3, 5, 9, 12]
left: 0 right: 5 middle: 2
left: 0 right: 2 middle: 1
移除元素
给定一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 \(O(1)\) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1: 1
给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
1
给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。你不需要考虑数组中超出新长度后面的元素。
1. 暴力解法双指针
2. 快慢指针法
暴力解法:
双循环一个循环遍历数组,第二个循环更新数组。from:代码随想录
1 | def removeVal(nums: list, val: int)-> int: |
执行步骤:
nums = [3, 2, 2, 3]
val = 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23round 1:
[3, 2, 2, 3]
^
the current element is the value! remove it
Now the nums change into: [2, 2, 3, 3]
size now is: 3
---------------------
round 2:
[2, 2, 3, 3]
^
---------------------
round 3:
[2, 2, 3, 3]
^
---------------------
round 4:
[2, 2, 3, 3]
^
the current element is the value! remove it
Now the nums change into: [2, 2, 3, 3]
size now is: 2
---------------------
finished!
空间复杂度: \(O(1)\)
快慢指针解法
快指针:用来寻找不等于val
的元素慢指针:用来记录新数组的下标
双指针一开始会同时移动,当遇到
val
元素时,慢指针在该元素停止,快指针继续向前寻找非val
的元素,找到时,慢指针处的元素为更新快指针的元素,两个指针继续同时移动。
from:代码随想录
1 | def removeVal(nums: list, val: int)-> int: |
例子:
nums = [0, 1, 2, 2, 3, 0, 4, 2, 3]
val = 2 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93----------ROUND 0-----------
fast
v
[0, 1, 2, 2, 3, 0, 4, 2, 3]
^
slow
----------ROUND 1-----------
fast
v
[0, 1, 2, 2, 3, 0, 4, 2, 3]
^
slow
----------ROUND 2-----------
fast
v
[0, 1, 2, 2, 3, 0, 4, 2, 3]
^
slow
*******FIND THE VAL!*******
----------ROUND 3-----------
fast
v
[0, 1, 2, 2, 3, 0, 4, 2, 3]
^
slow
*******FIND THE VAL!*******
----------ROUND 4-----------
fast
v
[0, 1, 2, 2, 3, 0, 4, 2, 3]
^
slow
*******NUMS UPDATE!*******
fast
v
[0, 1, 3, 2, 3, 0, 4, 2, 3]
^
----------ROUND 5-----------
fast
v
[0, 1, 3, 2, 3, 0, 4, 2, 3]
^
slow
*******NUMS UPDATE!*******
fast
v
[0, 1, 3, 0, 3, 0, 4, 2, 3]
^
----------ROUND 6-----------
fast
v
[0, 1, 3, 0, 3, 0, 4, 2, 3]
^
slow
*******NUMS UPDATE!*******
fast
v
[0, 1, 3, 0, 4, 0, 4, 2, 3]
^
----------ROUND 7-----------
fast
v
[0, 1, 3, 0, 4, 0, 4, 2, 3]
^
slow
*******FIND THE VAL!*******
----------ROUND 8-----------
fast
v
[0, 1, 3, 0, 4, 0, 4, 2, 3]
^
slow
*******NUMS UPDATE!*******
fast
v
[0, 1, 3, 0, 4, 3, 4, 2, 3]
^
Finished!
Return: 6