Skip to content

Commit 359090a

Browse files
committed
Translation of The_key_to_resolving_TwoSum_problems.md
1 parent 7078491 commit 359090a

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# The key to resolving Two Sum problems
2+
3+
**Translator**: [Fulin Li](fulinli.github.io)
4+
5+
**Author**:[labuladong](https://github.com/labuladong)
6+
7+
There are a series of problems with Two Sum in LeetCode, and this article will pick out some representative problems to demonstrate how to resolve the Two Sum problems.
8+
9+
### TwoSum I
10+
11+
**The most basic form** of Two Sum problems is like this: Given an array of integers `nums`, and a specific integer `target`. You may assume that each input would have **exactly** one solution. return indices of the two numbers such that they add up to target.
12+
13+
For example, given `nums = [3,1,3,6], target = 6`, the program should return an array `[0,2]` as 3 + 3 = 6.
14+
15+
So, how to solve this problem? First, the simplest method, of course, is the exhaustive search.
16+
17+
```java
18+
int[] twoSum(int[] nums, int target) {
19+
20+
for (int i = 0; i < nums.length; i++)
21+
for (int j = i + 1; j < nums.length; j++)
22+
if (nums[j] == target - nums[i])
23+
return new int[] { i, j };
24+
25+
// If no such two numbers exists
26+
return new int[] {-1, -1};
27+
}
28+
```
29+
30+
This method is straightforward. The time complexity is $O(n^2)$ and space complexity is $O(1)$.
31+
32+
We can use a hash table to reduce the time complexity:
33+
34+
```java
35+
int[] twoSum(int[] nums, int target) {
36+
int n = nums.length;
37+
index<Integer, Integer> index = new HashMap<>();
38+
// Constructing a hash table: Elements are mapped to their corresponding indices
39+
for (int i = 0; i < n; i++)
40+
index.put(nums[i], i);
41+
42+
for (int i = 0; i < n; i++) {
43+
int other = target - nums[i];
44+
// IF 'other' exists and it is not nums[i].
45+
if (index.containsKey(other) && index.get(other) != i)
46+
return new int[] {i, index.get(other)};
47+
}
48+
49+
return new int[] {-1, -1};
50+
}
51+
```
52+
53+
In this way, because the query time of a hash table is O(1) and the time complexity of the algorithm is reduced to O(N). However, the space complexity is increased to O(N) for storing the hash table. Generally, it is more efficient than the exhaustive search method.
54+
55+
**I think the objective of the two sum problems is to tell us how to use the hash table.** Let's go on to the next.
56+
57+
### TwoSum II
58+
59+
We can modify the last script slightly to design a class with two API:
60+
61+
```java
62+
class TwoSum {
63+
// Add a 'number' to data structure
64+
public void add(int number);
65+
// Find out whether there exists two numbers and their sum is equal to 'value'
66+
public boolean find(int value);
67+
}
68+
```
69+
70+
So how to implement these two functions? We can follow the last problem and use a hash table to realize the 'find' function.
71+
72+
```java
73+
class TwoSum {
74+
Map<Integer, Integer> freq = new HashMap<>();
75+
76+
public void add(int number) {
77+
// Recording the number of times that number has occurred
78+
freq.put(number, freq.getOrDefault(number, 0) + 1);
79+
}
80+
81+
public boolean find(int value) {
82+
for (Integer key : freq.keySet()) {
83+
int other = value - key;
84+
// Situation 1
85+
if (other == key && freq.get(key) > 1)
86+
return true;
87+
// Situation 2
88+
if (other != key && freq.containsKey(other))
89+
return true;
90+
}
91+
return false;
92+
}
93+
}
94+
```
95+
96+
When diving into `find` function, there are two situations, for example:
97+
98+
Situation 1: After `[3,3,2,5]` is inputted in `add` function, `find(6)` is executed. There are two `3` exists and 3 + 3 = 6, thus, it will return true.
99+
100+
Situation 2: After `[3,3,2,5]` is inputted in `add` function, `find(7)` is executed. Only when `key` is equal to 2 and `other` is equal to 5, it will return true.
101+
102+
Except as the two situations mentioned above, `find` will only return false.
103+
104+
What's the time complexity of this algorithm? The time complexity of `add` function is O(1), `find` function is O(N), and the space complexity is O(N), which is similar to the last problem.
105+
106+
**However, we should take realities of the situation into account in API design.** For example, in our class, the function `find` is used very frequently and each time it requires O(N) times. It is a huge waste of time. Can we optimize the algorithm given in this situation?
107+
108+
Of course, we can optimize the algorithm when `find` function is used frequently. We can refer to the brute force method in the last problem and utilize a hash set to optimize `find` function pertinently.
109+
110+
```java
111+
class TwoSum {
112+
Set<Integer> sum = new HashSet<>();
113+
List<Integer> nums = new ArrayList<>();
114+
115+
public void add(int number) {
116+
// Recording all possible sum of two numbers
117+
for (int n : nums)
118+
sum.add(n + number);
119+
nums.add(number);
120+
}
121+
122+
public boolean find(int value) {
123+
return sum.contains(value);
124+
}
125+
}
126+
```
127+
128+
In this way, all possible sum of two numbers is stored in `sum`. Every time `find` function takes O(1) time to search whether the target exists in the collection. Obviously, it is very suitable for frequent use of find function.
129+
130+
### Summary
131+
132+
For TwoSum problems, one of the difficulties is that the given array is **unordered**. For an unordered array, it seems that we don't have any efficient methods and an exhaustive search method may be the only way.
133+
134+
**In ordinary circumstances, we will sort the unordered array first and then consider applying the dual-pointer method.** TwoSum problems make us aware that HashMap or HashSet could help us to resolve unordered array problems.
135+
136+
Besides, the core of algorithm design is a trade-off, using different data structures to improve the algorithm performance pertinently.
137+
138+
Finally, if the given array in TwoSum I is ordered, how do we design the algorithm? It's very easy and you can refer to the previous article「Summary of usage of dual-pointer」:
139+
140+
```java
141+
int[] twoSum(int[] nums, int target) {
142+
int left = 0, right = nums.length - 1;
143+
while (left < right) {
144+
int sum = nums[left] + nums[right];
145+
if (sum == target) {
146+
return new int[]{left, right};
147+
} else if (sum < target) {
148+
left++; // Make sum bigger
149+
} else if (sum > target) {
150+
right--; // Make sum smaller
151+
}
152+
}
153+
// If no such two numbers exists
154+
return new int[]{-1, -1};
155+
}
156+
```
157+
158+
**Mission**: Stick to original high-quality articles, and work hard to make algorithmic problems clear. Welcome to subscribe my Wechat public account `ID:labuladong` for latest articles.

0 commit comments

Comments
 (0)