Reputation: 369
I'm new to Java and I just started to do Leetcode - Two Sum. I found that except brute force solution, the common solution is using Hashmap. But I still cannot get it. For example, this works in my logic:
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
int[] res = new int[2];
for (int i = 0; i < nums.length; ++i) {
m.put(nums[i], i);
}
for (int i = 0; i < nums.length; ++i) {
int t = target - nums[i];
if (m.containsKey(t) && m.get(t) != i) {
res[0] = i;
res[1] = m.get(t);
break;
}
}
return res;
}
The first for loop put numbers to Hashmap, and use the second for loop to check if we can find the number that equals to target number - nums[i]
. However, I saw a lot of accepted solutions combined the two for loops, such as this example:
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
int[] res = new int[2];
for (int i = 0; i < nums.length; ++i) {
if (m.containsKey(target - nums[i])) {
res[0] = i;
res[1] = m.get(target - nums[i]);
break;
}
m.put(nums[i], i);
}
return res;
}
In my logic, the second solution run the for loop like this:
//[2,7,11,15]
when i=0, m.put(nums[0],2)
when i=1, m.put(nums[1],7)
when i=2, m.put(nums[2],11)
when i=3, m.put(nums[3],15)
And because i < nums.length
so when i=4, the code will jump to return res
. It won't run the for loop again. But as far as I know, I saw people say that the second solution will iterate through the array, and store the index and value to Hashmap and then iterate again. In my imagination there's only one for loop, how can they use the only one for loop to iterate again?
Upvotes: 2
Views: 10937
Reputation: 1242
The LeetCode solution is a variation of your HashMap
solution.
Imagine that nums[j] + nums[k] = target
for some indices j and k, j < k, and you don't break
in your second for
loop. Then the condition in that loop will trigger twice: for i = j
and for i = k
. Then imagine that you don't care about the first trigger and okay if the condition only triggers for i = k
. This is what the LeetCode solution does. Since when i = j
the nums[j]
is not yet in the map, the condition won't trigger. It will only trigger when i = k
, that is, when the first element of the pair is in the map.
For example, consider nums
= [2,7,11,15] and target
= 13.
Here is the breakdown how your solution without break
would work.
i |
nums[i] |
target - nums[i] |
in the map? |
---|---|---|---|
0 | 2 | 11 | ✓ |
1 | 7 | 5 | |
2 | 11 | 2 | ✓ |
3 | 15 | −2 |
(The last column is marked when the value of target - nums[i]
is in the map during the check.)
Compare this with the rundown for the LeetCode solution with removed break
:
i |
nums[i] |
target - nums[i] |
map keys | in the map? |
---|---|---|---|---|
0 | 2 | 11 | [] | |
1 | 7 | 5 | [2] | |
2 | 11 | 2 | [2, 7] | ✓ |
3 | 15 | −2 | [2, 7, 11] |
The LeetCode solution cuts on the number of insertions into the map when the solution is found early. In the worst case, when there are no such j and k, both solutions make the same number of insertions and contains
queries.
Upvotes: 0
Reputation: 1
I think this is the best way to solve this question
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
for (int i=0; i<nums.length; i++){
for (int j=i+1; j<nums.length; j++){
if (nums[i] + nums[j] == target){
result[0]=i;
result[1]=j;
return result;
}
}
}
return result;
}
}
Upvotes: 0
Reputation: 36
There is no need for two for loops and this can be done in the single for loop as posted by you.From a perfomance point of view its better to iterate only once in the for loop and break from the loop when the first matching pair is found. This is O(n) in the worst case.
public static int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
int rem = target - num;
if (map.containsKey(rem)) {
return new int[] { num, rem };
}
map.put(num, num);
} // for
return null;
}
Upvotes: 1
Reputation: 1297
there wont be any 2nd iteration. In one iteration itself the loop would break if a pair is found.
consider this:
//[2,7,11,15] and target = 13
when i=0, m.put(mums[0],2)
when i=1, m.put(mums[1],7)
when i=2, m.contains(13 - mums[2]) == true // since 13 - 11 = 2 is present at index 0
res[0] = 2
res[1] = 0
break;
and Hence, ..... you are right. there is only one iteration.
Upvotes: 2