|
8 | 8 |
|
9 | 9 | - 按照数组下标取数的时间复杂度为 O(1)
|
10 | 10 |
|
| 11 | +**解题思路** |
| 12 | + |
11 | 13 | 1. 从头到尾依次扫描这个数组中的每个数字。
|
12 | 14 | 2. 当扫描到下标为 i 的数字时,首先比较这个数字(用 m 表示)是不是等于 i,如果是,则接着扫描下一个数字;如果不是,则再拿它和第 m 个数字进行比较。
|
13 | 15 | 3. 如果它和第 m 个数字相等,就找到了一个重复的数字(该数字在下标为 i 和 m 的位置都出现了);
|
|
16 | 18 | **时间复杂度 O(n),空间复杂度 O(1)**
|
17 | 19 |
|
18 | 20 | ```python
|
19 |
| -## start |
20 |
| -## 循环数组 |
21 |
| -def start(input_array): |
22 |
| - start.result = '重复数字为:' |
23 |
| - start.flag = True |
24 |
| - |
25 |
| - for i in range(len(input_array)): |
26 |
| - if start.flag: |
27 |
| - compare(i) |
28 |
| - else: |
29 |
| - return |
30 |
| - |
31 |
| - print(start.result) |
32 |
| - |
33 |
| - |
34 |
| -## 定义比较函数 |
35 |
| -def compare(i): |
36 |
| - global result |
37 |
| - |
38 |
| - if input_array[i] == i: |
39 |
| - pass |
40 |
| - else: |
41 |
| - ## 异常判断 |
42 |
| - try: |
43 |
| - if input_array[i] == input_array[input_array[i]]: |
44 |
| - start.result = start.result + str(input_array[i]) + ',' |
| 21 | +from typing import List |
| 22 | + |
| 23 | +class Solution: |
| 24 | + def findRepeatNumber(self, nums: List[int]) -> int: |
| 25 | + self.result = [] |
| 26 | + self.flag = True |
| 27 | + |
| 28 | + for i in range(len(nums)): |
| 29 | + if self.flag: |
| 30 | + self.compare(i, nums) |
45 | 31 | else:
|
46 |
| - temp = input_array[i] |
47 |
| - input_array[i] = input_array[input_array[i]] |
48 |
| - input_array[temp] = temp |
49 |
| - compare(i) |
50 |
| - |
51 |
| - except: |
52 |
| - print('输入数组不合规!') |
53 |
| - start.flag = False |
54 |
| - |
55 |
| - |
56 |
| -input_array = [2, 3, 1, 0, 2, 5, 3] |
57 |
| -start(input_array) |
58 |
| - |
| 32 | + return |
| 33 | + |
| 34 | + if self.flag: |
| 35 | + print('重复数字为:', self.result) |
| 36 | + if len(self.result) != 0 : return(self.result[0]) |
| 37 | + |
| 38 | + |
| 39 | + ## 定义比较函数 |
| 40 | + def compare(self, i, nums): |
| 41 | + |
| 42 | + if nums[i] == i: |
| 43 | + pass |
| 44 | + else: |
| 45 | + ## 异常判断 |
| 46 | + try: |
| 47 | + if nums[i] == nums[nums[i]]: |
| 48 | + self.result.append(nums[i]) |
| 49 | + else: |
| 50 | + temp = nums[i] |
| 51 | + nums[i] = nums[nums[i]] |
| 52 | + nums[temp] = temp |
| 53 | + self.compare(i, nums) |
| 54 | + |
| 55 | + except: |
| 56 | + print('输入数组不合规!') |
| 57 | + self.flag = False |
| 58 | + |
| 59 | +input_array = [2, 3, 1, 0, 2, 5, 5] |
| 60 | +s = Solution() |
| 61 | +s.findRepeatNumber(input_array) |
| 62 | +``` |
| 63 | + |
| 64 | +输出为: |
| 65 | + |
| 66 | +``` |
| 67 | +重复数字为: [2, 5] |
59 | 68 | ```
|
60 | 69 |
|
61 |
| -重复数字为:2,3, |
| 70 | + |
62 | 71 |
|
63 | 72 | **Inverview3-1测试用例**
|
64 | 73 |
|
65 | 74 | ```python
|
66 | 75 | ## 长度为n的数组里包含一个或者多个重复的数字
|
67 | 76 | input_array = [4,3,2,4,5,5]
|
68 |
| -start(input_array) |
| 77 | +s.findRepeatNumber(input_array) |
69 | 78 |
|
70 | 79 | ## 数组中不包含重复数字
|
71 | 80 | input_array = [4,1,2,0,5,3,6]
|
72 |
| -start(input_array) |
| 81 | +s.findRepeatNumber(input_array) |
73 | 82 |
|
74 | 83 | ## 无效输入测试用例--空数组
|
75 | 84 | input_array = []
|
76 |
| -start(input_array) |
| 85 | +s.findRepeatNumber(input_array) |
77 | 86 |
|
78 | 87 | ## 无效输入测试用例--长度为n的数组中包含0——n-1 之外的数字
|
79 | 88 | input_array = [1,7,1,2,2]
|
80 |
| -start(input_array) |
| 89 | +s.findRepeatNumber(input_array) |
81 | 90 | ```
|
82 | 91 |
|
83 |
| -重复数字为:5,4, |
84 |
| - |
85 |
| -重复数字为: |
86 |
| - |
87 |
| -重复数字为: |
| 92 | +输出为: |
88 | 93 |
|
| 94 | +``` |
| 95 | +重复数字为: [5, 4] |
| 96 | +重复数字为: [] |
| 97 | +重复数字为: [] |
89 | 98 | 输入数组不合规!
|
| 99 | +``` |
90 | 100 |
|
91 | 101 |
|
92 | 102 |
|
93 | 103 | ## Inverview3-2:不修改数组找出重复的数字
|
94 | 104 |
|
95 | 105 | **题目**:在一个长度为 n+1 的数组里的所有数字都在 1~n 的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3。
|
96 | 106 |
|
| 107 | +**解题思路** |
| 108 | + |
97 | 109 | 1. 我们把从 1\~n 的数字从中间的数字 m 分为两部分,前面一半为 1\~m,后面一半为 m+1\~n。
|
98 | 110 | 2. 如果 1\~m 的数字的数目超过 m ,那么这一半的区间里一定包含重复的数字;否则,另一半 m+1\~n 的区间里一定包含重复的数字。
|
99 | 111 | 3. 我们可以继续把包含重复数字的区间一分为二,直到找到一个重复的数字。
|
100 | 112 |
|
101 | 113 | 代码按照二分查找的思路,如果输入长度为 n 的数组,那么遍历数组将被调用 O(logn) 次,每次需要 O(n) 的时间,因此总的时间复杂度是 O(nlogn) ,空间复杂度为 0(1) 。和最前面提到的需要 0(n) 的辅助空间的算法相比,这种算法相当于以时间换空间。
|
102 | 114 |
|
103 | 115 | ```python
|
| 116 | +from typing import List |
104 | 117 |
|
105 |
| -## start |
106 |
| -def start(input_array): |
107 |
| - if len(input_array) == 0: |
108 |
| - print('输入数组不合法!') |
109 |
| - return |
110 |
| - start_n = 1 |
111 |
| - end_n = len(input_array) - 1 |
112 |
| - flag = True |
113 |
| - |
114 |
| - ## 循环 |
115 |
| - while flag: |
116 |
| - middle = int((end_n - start_n) / 2) |
117 |
| - if middle == 0: |
118 |
| - flag = False |
119 |
| - middle = start_n + middle |
120 |
| - left_n = 0 |
121 |
| - right_n = 0 |
| 118 | +class Solution: |
| 119 | + def findRepeatNumber(self, nums: List[int]) -> int: |
| 120 | + if len(nums) == 0: |
| 121 | + print('输入数组不合法!') |
| 122 | + return |
122 | 123 |
|
123 |
| - ## 开始比较数字,分区域统计 |
124 |
| - for num in input_array: |
125 |
| - if num <= middle and num >= start_n: |
126 |
| - left_n += 1 |
127 |
| - elif num > middle and num <= end_n: |
128 |
| - right_n += 1 |
129 |
| - elif end_n + start_n == len(input_array): |
130 |
| - print('输入数组不合法!') |
| 124 | + start_n = 1 |
| 125 | + end_n = len(nums) - 1 |
| 126 | + flag = True |
| 127 | + |
| 128 | + ## 循环 |
| 129 | + while flag: |
| 130 | + middle = int((end_n - start_n) / 2) |
| 131 | + if middle == 0: |
131 | 132 | flag = False
|
132 |
| - |
133 |
| - ## 两边区域个数比较 |
134 |
| - if left_n > middle - start_n + 1: |
135 |
| - end_n = middle |
136 |
| - if flag == False: |
137 |
| - print('重复数字为:',start_n) |
138 |
| - elif right_n > end_n - middle: |
139 |
| - start_n = middle + 1 |
140 |
| - if flag == False: |
141 |
| - print('重复数字为:',end_n) |
142 |
| - |
143 |
| - |
144 |
| -input_array = [2, 3, 5, 4, 1, 6, 3, 7] |
145 |
| -start(input_array) |
| 133 | + middle = start_n + middle |
| 134 | + left_n = 0 |
| 135 | + right_n = 0 |
| 136 | + |
| 137 | + ## 开始比较数字,分区域统计 |
| 138 | + for num in nums: |
| 139 | + if num <= middle and num >= start_n: |
| 140 | + left_n += 1 |
| 141 | + elif num > middle and num <= end_n: |
| 142 | + right_n += 1 |
| 143 | + elif end_n + start_n == len(nums): |
| 144 | + print('输入数组不合法!') |
| 145 | + flag = False |
| 146 | + |
| 147 | + ## 两边区域个数比较 |
| 148 | + if left_n > middle - start_n + 1: |
| 149 | + end_n = middle |
| 150 | + if flag == False: |
| 151 | + print('重复数字为:',start_n) |
| 152 | + elif right_n > end_n - middle: |
| 153 | + start_n = middle + 1 |
| 154 | + if flag == False: |
| 155 | + print('重复数字为:',end_n) |
| 156 | + |
| 157 | +input_array = [2, 3, 5, 3, 4, 6, 3, 7] |
| 158 | +s = Solution() |
| 159 | +s.findRepeatNumber(input_array) |
146 | 160 | ```
|
147 | 161 |
|
| 162 | +结果如下: |
| 163 | + |
| 164 | +``` |
148 | 165 | 重复数字为: 3
|
| 166 | +``` |
| 167 | + |
| 168 | + |
149 | 169 |
|
150 | 170 | **Inverview3-2测试用例**
|
151 | 171 |
|
152 | 172 | ```python
|
153 | 173 | ## 长度为n的数组里包含一个或者多个重复的数字
|
154 | 174 | input_array = [2, 3, 5, 4, 1, 4, 3, 7]
|
155 |
| -start(input_array) |
| 175 | +s.findRepeatNumber(input_array) |
156 | 176 |
|
157 | 177 | ## 数组中不包含重复数字
|
158 | 178 | input_array = [2, 3, 5, 4, 1, 6, 8, 7]
|
159 |
| -start(input_array) |
| 179 | +s.findRepeatNumber(input_array) |
160 | 180 |
|
161 | 181 | ## 输入空数组
|
162 | 182 | input_array = []
|
163 |
| -start(input_array) |
| 183 | +s.findRepeatNumber(input_array) |
164 | 184 | ```
|
165 | 185 |
|
166 |
| -重复数字为: 3 |
| 186 | +结果如下: |
167 | 187 |
|
| 188 | +``` |
| 189 | +重复数字为: 3 |
168 | 190 | 输入数组不合法!
|
169 |
| - |
170 | 191 | 输入数组不合法!
|
171 |
| - |
172 |
| - |
173 |
| - |
174 |
| ------- |
175 |
| - |
176 |
| -> 作者:[@mantchs](https://github.com/NLP-LOVE/ML-NLP) |
177 |
| -> |
178 |
| -> GitHub:[https://github.com/NLP-LOVE/CodingInterviews2-ByPython](https://github.com/NLP-LOVE/CodingInterviews2-ByPython) |
179 |
| -> |
180 |
| -> 有意向一起完成此项目或者有问题、有补充的可以加入《剑指offer》讨论群【818185620】<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=8c188e86e0eac4a214861c2c706a9c0baf75176e16e52f07b8a64d1a13f99a0d"><img border="0" src="http://pub.idqqimg.com/wpa/images/group.png" alt="《剑指offer》讨论群" title="《剑指offer》讨论群"></a> |
| 192 | +``` |
0 commit comments