From 06190f2f1947f4421234ea7912c51fb07d5c79a9 Mon Sep 17 00:00:00 2001
From: CyC2018 <1029579233@qq.com>
Date: Tue, 28 Aug 2018 22:55:26 +0800
Subject: [PATCH] auto commit
---
notes/算法.md | 78 +++++++++++++++++++++++++++++++++++++--------------
1 file changed, 57 insertions(+), 21 deletions(-)
diff --git a/notes/算法.md b/notes/算法.md
index a9f9e689..53edc1c1 100644
--- a/notes/算法.md
+++ b/notes/算法.md
@@ -104,17 +104,21 @@ public class ThreeSumSlow implements ThreeSum {
public int count(int[] nums) {
int N = nums.length;
int cnt = 0;
- for (int i = 0; i < N; i++)
- for (int j = i + 1; j < N; j++)
- for (int k = j + 1; k < N; k++)
- if (nums[i] + nums[j] + nums[k] == 0)
+ for (int i = 0; i < N; i++) {
+ for (int j = i + 1; j < N; j++) {
+ for (int k = j + 1; k < N; k++) {
+ if (nums[i] + nums[j] + nums[k] == 0) {
cnt++;
+ }
+ }
+ }
+ }
return cnt;
}
}
```
-### 2. ThreeSumFast
+### 2. ThreeSumBinarySearch
通过将数组先排序,对两个元素求和,并用二分查找方法查找是否存在该和的相反数,如果存在,就说明存在三元组的和为 0。
@@ -123,19 +127,23 @@ public class ThreeSumSlow implements ThreeSum {
该方法可以将 ThreeSum 算法增长数量级降低为 O(N2logN)。
```java
-public class ThreeSumFast {
- public static int count(int[] nums) {
+public class ThreeSumBinarySearch implements ThreeSum {
+
+ @Override
+ public int count(int[] nums) {
Arrays.sort(nums);
int N = nums.length;
int cnt = 0;
- for (int i = 0; i < N; i++)
+ for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
int target = -nums[i] - nums[j];
int index = BinarySearch.search(nums, target);
// 应该注意这里的下标必须大于 j,否则会重复统计。
- if (index > j)
+ if (index > j) {
cnt++;
+ }
}
+ }
return cnt;
}
}
@@ -143,22 +151,59 @@ public class ThreeSumFast {
```java
public class BinarySearch {
+
public static int search(int[] nums, int target) {
int l = 0, h = nums.length - 1;
while (l <= h) {
int m = l + (h - l) / 2;
- if (target == nums[m])
+ if (target == nums[m]) {
return m;
- else if (target > nums[m])
+ } else if (target > nums[m]) {
l = m + 1;
- else
+ } else {
h = m - 1;
+ }
}
return -1;
}
}
```
+### 3. ThreeSumTwoPointer
+
+更有效的方法是先将数组排序,然后使用双指针进行查找,时间复杂度为 O(N2)。
+
+```java
+public class ThreeSumTwoPointer implements ThreeSum {
+
+ @Override
+ public int count(int[] nums) {
+ int N = nums.length;
+ int cnt = 0;
+ Arrays.sort(nums);
+ for (int i = 0; i < N - 2; i++) {
+ int l = i + 1, h = N - 1, target = -nums[i];
+ if (i > 0 && nums[i] == nums[i - 1]) continue;
+ while (l < h) {
+ int sum = nums[l] + nums[h];
+ if (sum == target) {
+ cnt++;
+ while (l < h && nums[l] == nums[l + 1]) l++;
+ while (l < h && nums[h] == nums[h - 1]) h--;
+ l++;
+ h--;
+ } else if (sum < target) {
+ l++;
+ } else {
+ h--;
+ }
+ }
+ }
+ return cnt;
+ }
+}
+```
+
## 倍率实验
如果 T(N) \~ aNblogN,那么 T(2N)/T(N) \~ 2b。
@@ -180,29 +225,20 @@ public class BinarySearch {
public class RatioTest {
public static void main(String[] args) {
-
int N = 500;
int loopTimes = 7;
double preTime = -1;
-
while (loopTimes-- > 0) {
-
int[] nums = new int[N];
-
StopWatch.start();
-
ThreeSum threeSum = new ThreeSumSlow();
-
int cnt = threeSum.count(nums);
System.out.println(cnt);
-
double elapsedTime = StopWatch.elapsedTime();
double ratio = preTime == -1 ? 0 : elapsedTime / preTime;
System.out.println(N + " " + elapsedTime + " " + ratio);
-
preTime = elapsedTime;
N *= 2;
-
}
}
}