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; - } } }