Skip to content

Commit 2ab8d55

Browse files
refactor 220
1 parent 99e4cac commit 2ab8d55

File tree

2 files changed

+98
-80
lines changed

2 files changed

+98
-80
lines changed

src/main/java/com/fishercoder/solutions/_220.java

Lines changed: 44 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,93 +4,57 @@
44

55
/**
66
* 220. Contains Duplicate III
7-
*
7+
* <p>
88
* Given an array of integers, find out whether there are two
99
* distinct indices i and j in the array such that the difference between nums[i] and nums[j] is at
1010
* most t and the difference between i and j is at most k.
1111
*/
1212
public class _220 {
13-
/**
14-
* TreeSet: per Java doc, is a NavigableSet implementation based on a TreeMap. The elements are ordered
15-
* using their natural ordering, or by a Comparator provided at set creation time, depending on
16-
* which constructor is used. This implementation provides guaranteed log(n) time cost for the
17-
* basic operations (add, remove and contains).
18-
*/
19-
20-
/**
21-
* TreeSet turns out to be a super handy data structure for this problem. It implements Set
22-
* interface and keeps elements in sorted order, plus it has two very handy APIs:
23-
*
24-
* https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html#ceiling(E): Returns the
25-
* least element in this set greater than or equal to the given element, or null if there is no
26-
* such element.
27-
*
28-
* https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html#floor(E): Returns the
29-
* greatest element in this set less than or equal to the given element, or null if there is no
30-
* such element.
31-
*
32-
* Idea: loop through this array, keep adding each element into the TreeSet, also keep an eye on
33-
* the size of the TreeSet, if it's greater than the required distance of k, then we remove the
34-
* left-most or oldest one from the set. For each element, we get the current floor and the
35-
* current ceiling and see if it works, if it does, then we return true immediately, otherwise,
36-
* we continue. Return false when we finished the loop.
37-
*/
3813

39-
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
40-
TreeSet<Integer> set = new TreeSet<Integer>();
41-
for (int i = 0; i < nums.length; i++) {
42-
Integer s = set.ceiling(nums[i]);//take the smallest greater number than nums[i] is there exists
43-
if (s != null && s - nums[i] <= t) {
44-
return true;//it must be s - nums[i] here, otherwise, cases like [4,2] 2, 1 wont' pass, because we'll get 2-4 = -2 which is a negative number that for sure will be smaller than t
45-
}
46-
Integer g = set.floor(nums[i]);//take the biggest smaller number than nums[i] if there exists
47-
if (g != null && (long) nums[i] - g <= t) {
48-
return true;
49-
}
50-
set.add(nums[i]);
51-
if (set.size() > k) {
52-
set.remove(nums[i - k]);//set doesn't have indices and it's not ordered, we could only specify the element
53-
//that we want to remove, this element is nums[i-k]
14+
public static class Solution1 {
15+
/**
16+
* TreeSet: per Java doc, is a NavigableSet implementation based on a TreeMap. The elements are ordered
17+
* using their natural ordering, or by a Comparator provided at set creation time, depending on
18+
* which constructor is used. This implementation provides guaranteed log(n) time cost for the
19+
* basic operations (add, remove and contains).
20+
*/
21+
22+
/**
23+
* TreeSet turns out to be a super handy data structure for this problem. It implements Set
24+
* interface and keeps elements in sorted order, plus it has two very handy APIs:
25+
* <p>
26+
* https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html#ceiling(E): Returns the
27+
* least element in this set greater than or equal to the given element, or null if there is no
28+
* such element.
29+
* <p>
30+
* https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html#floor(E): Returns the
31+
* greatest element in this set less than or equal to the given element, or null if there is no
32+
* such element.
33+
* <p>
34+
* Idea: loop through this array, keep adding each element into the TreeSet, also keep an eye on
35+
* the size of the TreeSet, if it's greater than the required distance of k, then we remove the
36+
* left-most or oldest one from the set. For each element, we get the current floor and the
37+
* current ceiling and see if it works, if it does, then we return true immediately, otherwise,
38+
* we continue. Return false when we finished the loop.
39+
*/
40+
41+
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
42+
TreeSet<Integer> set = new TreeSet<>();
43+
for (int i = 0; i < nums.length; ++i) {
44+
// Find the successor of current element
45+
Integer s = set.ceiling(nums[i]);
46+
if (s != null && s <= nums[i] + t) return true;
47+
48+
// Find the predecessor of current element
49+
Integer g = set.floor(nums[i]);
50+
if (g != null && nums[i] <= g + t) return true;
51+
52+
set.add(nums[i]);
53+
if (set.size() > k) {
54+
set.remove(nums[i - k]);
55+
}
5456
}
57+
return false;
5558
}
56-
return false;
57-
}
58-
59-
/**
60-
* converting to (long) is essential, otherwise cases like this:
61-
* <p>
62-
* [-1,2147483647]
63-
* <p>
64-
* 1
65-
* <p>
66-
* 2147483647
67-
* <p>
68-
* will overflow, i.e. Integer in Java is 32 bit which means Integer.MAX_VALUE =2147483647 and
69-
* Integer.MIN_VALUE = -2147483648, thus 2147483647 -(-1) = 2147483647+1 =-2147483648 instead of
70-
* 2147483648 (Java Integer won’t have this number), causing this test case to fail.
71-
*/
72-
73-
public static void main(String... strings) {
74-
_220 test = new _220();
75-
// int[] nums = new int[]{-1, -1};
76-
// int k = 1;
77-
// int t = 0;
78-
79-
// int[] nums = new int[] { 1, 2 };
80-
// int k = 0;
81-
// int t = 1;
82-
83-
int[] nums = new int[]{4, 2};
84-
int k = 2;
85-
int t = 1;
86-
87-
// int[] nums = new int[]{2, 2};
88-
// int k = 3;
89-
// int t = 0;
90-
91-
// int[] nums = new int[]{1};
92-
// int k = 1;
93-
// int t = 1;
94-
System.out.println(test.containsNearbyAlmostDuplicate(nums, k, t));
9559
}
9660
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.fishercoder;
2+
3+
import com.fishercoder.solutions._220;
4+
import org.junit.BeforeClass;
5+
import org.junit.Test;
6+
7+
import static org.junit.Assert.assertEquals;
8+
9+
public class _220Test {
10+
private static _220.Solution1 solution1;
11+
private static int[] nums;
12+
13+
@BeforeClass
14+
public static void setup() {
15+
solution1 = new _220.Solution1();
16+
}
17+
18+
@Test
19+
public void test1() {
20+
nums = new int[]{-1, -1};
21+
assertEquals(true, solution1.containsNearbyAlmostDuplicate(nums, 1, 0));
22+
}
23+
24+
@Test
25+
public void test2() {
26+
nums = new int[]{1, 2};
27+
assertEquals(false, solution1.containsNearbyAlmostDuplicate(nums, 0, 1));
28+
}
29+
30+
@Test
31+
public void test3() {
32+
nums = new int[]{4, 2};
33+
assertEquals(false, solution1.containsNearbyAlmostDuplicate(nums, 2, 1));
34+
}
35+
36+
@Test
37+
public void test4() {
38+
nums = new int[]{2, 2};
39+
assertEquals(true, solution1.containsNearbyAlmostDuplicate(nums, 3, 0));
40+
}
41+
42+
@Test
43+
public void test5() {
44+
nums = new int[]{1};
45+
assertEquals(false, solution1.containsNearbyAlmostDuplicate(nums, 1, 1));
46+
}
47+
48+
@Test
49+
public void test6() {
50+
nums = new int[]{2147483647, -2147483647};
51+
assertEquals(false, solution1.containsNearbyAlmostDuplicate(nums, 1, 2147483647));
52+
}
53+
54+
}

0 commit comments

Comments
 (0)