@@ -41,7 +41,7 @@ sum = 1 + 1 + n + 1+ n + n
41
41
= n (忽略低阶梯)
42
42
```
43
43
44
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-00.png )
44
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-00.png )
45
45
46
46
---
47
47
@@ -65,7 +65,7 @@ while (sum < n) {
65
65
这回我们只看执行次数最多的,很明显这是一个 ``` 2 * 2 * 2 ··· n ``` ,大于 n 跳出循环。
66
66
那么我们使用函数;2^x = n,x = logn,就可以表示出整体的时间复杂度为 O(logn)
67
67
68
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-07.png )
68
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-07.png )
69
69
70
70
好!结合这两个例子,相信你对时间复杂度已经有所理解,后面的算法题中就可以知道自己的算法是否好坏。
71
71
@@ -104,7 +104,7 @@ class Solution {
104
104
105
105
先不考虑时间复杂度的话,最直接的就是双层``` for ``` 循环,用每一个数和数组中其他数做家和比对,如下;
106
106
107
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-01.png )
107
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-01.png )
108
108
109
109
可以看到这样的时间复杂度是;n* (n-1) ··· 4* 3、4* 2、4* 1,也就是O(n!),有点像九九乘法表的结构。
110
110
@@ -127,15 +127,15 @@ public int[] twoSum(int[] nums, int target) {
127
127
128
128
** 耗时:**
129
129
130
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-02.png )
130
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-02.png )
131
131
132
132
- 对于这样的算法虽然能解决问题,但是并不能满足我们的需求,毕竟这个级别的时间复杂度下实在是太慢了。
133
133
134
134
### 思路2,单层循环
135
135
136
136
为了把这样一个双层循环简化为单层,我们最能直接想到的就事放到 Map 这样的数据结构中,方便我们存取比对。那么这样的一个计算过程如下图;
137
137
138
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-03.png )
138
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-03.png )
139
139
140
140
- 这个过程的核心内容是将原来的两数之和改成差值计算,并将每次的差与 Map 中元素进行比对。如果差值正好存在 Map 中,那么直接取出。否则将数存入到 Map 中,继续执行。
141
141
- 这个过程就可以将原来的双层循环改为单层,时间复杂度也到了 O(n) 级别。
@@ -157,7 +157,7 @@ public static int[] twoSum(int[] nums, int target) {
157
157
158
158
** 耗时:**
159
159
160
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-04.png )
160
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-04.png )
161
161
162
162
- 可以看到当我们使用 Map 结构的时候,整个执行执行用时已经有了很大的改善。但是你有考虑过``` containsKey ``` 与 ``` get ``` 是否为 null 相比哪个快吗?
163
163
- 这个算法已经很良好了,但是这个对 key 值的比对还是很耗时的,需要反复的对 map 进行操作,那么我们还需要再优化一下。
@@ -166,7 +166,7 @@ public static int[] twoSum(int[] nums, int target) {
166
166
167
167
如果说想把我们上面使用 Map 结构的地方优化掉,我们可以考虑下 Map 数据是如何存放的,他有一种算法是自身扩容 2^n - 1 & 元素,求地址。之后按照地址在进行存放数据。那么我们可以把这部分算法拿出来,我们自己设计一个数组结构,将元素进行与运算存放到我们自己定义的数组中。如下图;
168
168
169
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-05.png )
169
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-05.png )
170
170
171
171
- 左侧是我们假定的入参``` int[] nums ``` ,32是我们设定的值,这个值的设定需要满足存放大小够用,否则地址会混乱。
172
172
- 接下来我们使用 32 - 1,也就是二进制 ``` 011111 ``` 与每一个数组中的值进行与运算,求存放地址。
@@ -192,7 +192,7 @@ public static int[] towSum(int[] nums, int target) {
192
192
193
193
** 耗时:**
194
194
195
- ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/0001-06.png )
195
+ ![ ] ( http://niubility-algorithm.itstack.org/assets/img/2020/niubility-algorithm- 0001-06.png )
196
196
197
197
- 出现0毫秒耗时,100%击败,这个不一定每次都这样,可能你试的时候不一样。得益于数据结构的优化使得这个算法的耗时很少。
198
198
0 commit comments