前言:
一直有刷题习惯,最近才看到掘金举办了刷题活动,特来参加!
掘金团队号上线,助你 Offer 临门! 点击 查看详情
一、题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
样例1:
给出 numbers = [2, 7, 11, 15], target = 9, 返回 [0, 1].
样例2:
给出 numbers = [15, 2, 7, 11], target = 9, 返回 [1, 2].
二、思路分析:
| 方法 | 描述 | 时间复杂度 | 空间复杂度 |
|---|---|---|---|
| 双指针法 | 先排序后双指针 | ||
| 哈希表法 | 根据num[i],找targe-num[i] |
哈希表法
遍历i次,每一次都去查哈希表中是否存在target-nums[i],存在则返回position和i,不存在则存入哈希表.
伪代码如下:
for...
searchkey = target - nums[i]
if hashmap.containsKey(searchkey )
return hashmap.get(searchkey ),i
else
hashmap.put(nums[i])
双指针
然后对数组排序,在排序后的数组中利用双指针从左右向中间寻找
- 如果numbers[i] + numbers [j] == target 说明找到答案
- 如果numbers[i] + numbers [j] < target 说明当前和比答案小。左指针右移
- 如果numbers[i] + numbers [j] > target 说明当前和比答案大。右指针左移
然后在拷贝数组中找到对应numbers[i]和numbers[j] 的下标,对这两个下标排个序
三、AC 代码:
哈希表法
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
/*
* @lc app=leetcode.cn id=1 lang=java
*
* [1] 两数之和
*/
// @lc code=start
class Solution {
/**
*
* @param nums
* @param target
* @return fix bug need origin index ;is not value
*/
public int[] twoSum(int[] nums, int target) {
// key : origin value
// value: position
HashMap<Integer, Integer> hashMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int searchValue = target - nums[i];
if(hashMap.containsKey(searchValue)){
int[] res = {hashMap.get(searchValue),i};
return res;
}
hashMap.put(nums[i],i);
}
return new int[]{-1,-1};
}
}
// @lc code=end
双指针法
/*
* @lc app=leetcode.cn id=1 lang=java
*
* [1] 两数之和
*/
// @lc code=start
class Solution {
/**
* key: origin value value: origin position
*/
class NumMap {
Integer currentNum = 0;
Integer currentIndex = 0;
public NumMap(Integer number, Integer position) {
this.currentNum = number;
this.currentIndex = position;
}
public Integer getCurrentNum() {
return this.currentNum;
}
}
class ValueComparator implements Comparator<NumMap> {
@Override
public int compare(NumMap o1, NumMap o2) {
return o1.getCurrentNum().compareTo(o2.getCurrentNum());
}
}
/**
*
* @param nums
* @param target
* @return fix bug need origin index ;is not value
*/
public int[] twoSum(int[] nums, int target) {
// back conditions
int[] result = new int[] { -1, -1 };
if (nums == null) {
return result;
}
NumMap[] list = new NumMap[nums.length];
for (int i = 0; i < nums.length; i++) {
NumMap numMap = new NumMap(nums[i], i);
list[i] = numMap;
}
Arrays.sort(list, new ValueComparator());
int left = 0;
int right = nums.length - 1;
while (left < right) {
int currentSum = list[left].getCurrentNum() + list[right].getCurrentNum();
if (currentSum == target) {
result[0] = Math.min(list[left].currentIndex, list[right].currentIndex);
result[1] = Math.max(list[left].currentIndex, list[right].currentIndex);
break;
} else if (currentSum < target) {
left++;
} else {
right--;
}
}
return result;
}
}
// @lc code=end
总结
主要使用了哈希表法和双指针两种方法做这道题目。
- 双指针的时间复杂度是,空间复杂度是
- 哈希表法的时间复杂度是,空间复杂度是 空间和时间上两者差距并不大,仔细比较区别的话,两者最主要区别是:
- 双指针需要数组提前排好序,哈希表法对原数组是否有序不作要求
- 哈希表法需要使用临时的hashmap去存储以及判等,双指针需要使用自定义对象,判等排序