Topic overview
Give an array of integers that have been arranged in non decreasing order numbers ,Please find two numbers from the array. The sum of the two numbers is equal to the target number target .
The function should return the subscript values of these two numbers as an array of integers of length 2. numbers The subscript of is counted from 1, so the answer array should meet 1 <= answer[0] < answer[1] <= numbers.length .
You can assume that each input only corresponds to a unique answer, and you can't reuse the same elements.
Example 1:
Input: numbers = [2,7,11,15], target = 9
Output:[1,2]
Explanation: the sum of 2 and 7 is equal to the target number 9. therefore index1 = 1, index2 = 2 .
Example 2:
Input: numbers = [2,3,4], target = 6
Output:[1,3]
Example 3:
Input: numbers = [-1,0], target = -1
Output:[1,2]
Tips:
2 <= numbers.length <= 3 * 10^4
-1000 <= numbers[i] <= 1000
numbers In non decreasing order
-1000 <= target <= 1000
Only one valid answer exists
Algorithm idea:
1. Hash table
- The hash table is used to store elements. key is the element of the array and value is the sequence number corresponding to the element
- Traverse the array to determine whether there is an element of target number current number in the hash table. If so, it indicates that the relationship is satisfied. Target number = hash table element + current number, and return the array of the subscript of the current number and the element value corresponding to the hash table
- If the relevant number is still not found after traversing the array, it means that the sum of the two numbers is not equal to the target number
Code implementation:
public int[] twoSum(int[] numbers, int target) {
Map<Integer,Integer> hashMap = new HashMap<>();
for(int i = 0; i < numbers.length; i++){
if(hashMap.containsKey(target - numbers[i])){
return new int[]{hashMap.get(target - numbers[i]) + 1,i + 1};
}
hashMap.put(numbers[i],i);
}
return new int[0];
}
Complexity analysis:
- Time complexity: O(n), where n is the length of array nums
- Space complexity: O(n)
2. Double pointer
- Because the array is incremented, the elements on the left must be larger than those on the right
- So you can choose double pointers, one pointer to the left element and one pointer to the right element
- If the sum of the elements on both sides is less than the target element, the number on the left is small, and the left pointer should point to the next element
- On the contrary, if the right pointer is larger than the target element, it means that the number on the right is large, and the right pointer should point to the previous element
- If the sum of the elements pointed to by the left and right pointers is equal to the target element, an array of two pointers is returned
- Otherwise, an empty array is returned
Code implementation:
public int[] twoSum(int[] numbers, int target) {
int left = 0;
int right = numbers.length - 1;
while(left < right){
if(numbers[left] + numbers[right] > target){
right--;
}else if(numbers[left] + numbers[right] < target){
left++;
}
else{
return new int[]{left + 1,right + 1};
}
}
return new int[0];
}
Complexity analysis:
- Time complexity: O(n), where n is the length of array nums
- Space complexity: O(1)
3. Double pointer + binary search
- Because the array is sorted in ascending order, the number between the two pointers can be added to the two pointers respectively and then compared with the target value
- If the sum of the middle number and the element pointed to by the left pointer is greater than the target value, the number pointed to by the right pointer is too large. The right pointer should be updated to the previous digit of the middle position
- On the contrary, if the sum of the middle number and the element pointed by the right pointer is less than the target value, it indicates that the number pointed by the left pointer is too large, and the left pointer should be updated to the last digit of the middle position
- At the same time, after the comparison, judge the size of the sum of the two pointers and the target number
- If the sum of the two pointers is still less than the target number, the left pointer is updated to point to the next bit
- Conversely, if the sum of the two pointers is still greater than the target number, the right pointer is updated to point to the previous bit
- If the result cannot be found after the left and right pointers meet, an empty array is returned
Code implementation:
public int[] twoSum(int[] numbers, int target) {
int left = 0;
int right = numbers.length - 1;
while(left < right){
int middle = left + (right - left) / 2;
if(numbers[left] + numbers[middle] > target){
right = middle - 1;
}
else if(numbers[right] + numbers[middle] < target){
left = middle + 1;
}
else if(numbers[left] + numbers[right] < target){
left++;
}
else if(numbers[left] + numbers[right] > target){
right--;
}
else{
return new int[]{left + 1, right + 1};
}
}
return new int[]{0,0};
}
Complexity analysis:
- Time complexity: O(n), where n is the length of array numbers, the best case is logn, and the worst case is n
- Space complexity: O(1)