一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
题目描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。
但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。
例如:nums = [1,5,15,23] target = 16 --> [0,2]
解法思路
假设存在任意两值 x,y ∈ nums 若存在 x + y = target --> y = target - x
在这里我们只需要求到 x 与 y 值相对应的nums索引假设为 i 与 j
1.暴力破解双循环法
循环遍历数组nums;x = nums[i],利用target - x = y 得到 y 去遍历数组nums 取得与之匹配的值的下标j 最后返回 [i,j]
class Solution {
public int[] twoSum(int[] nums, int target) {
int x, y;
for (int i = 0; i < nums.length; i++) {
x = nums[i];
y = target - x;
int j = getIndexOfValue(nums, y);
if (j > -1 && i != j) {
return new int[]{i, j};
}
}
return new int[0];
}
private int getIndexOfValue(int[] nums, int value) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] == value) return i;
}
return -1;
}
}
2.暴力破解优化版本
在上面循环中我们会发现,假如在一次循环中 x = nums[i] 通过计算的 y 找不到符合的 j 反之可得出 i 不可能是正确答案中的一个.
我们应该在内层寻找 y 的下标 j 的循环中排除 x 对应的下标 i
循环遍历数组nums; x = nums[i],利用target - x = y 得到 y 去遍历数组nums 这时从 i 以后开始遍历,取得与之匹配的值的下标j 最后返回 [i,j]
class Solution {
public int[] twoSum(int[] nums, int target) {
int x, y;
for (int i = 0; i < nums.length; i++) {
x = nums[i];
y = target - x;
int j = getIndexOfValue(nums, y, i);
if (j > -1 && i != j) {
return new int[]{i, j};
}
}
return new int[0];
}
private int getIndexOfValue(int[] nums, int value, int startIndex) {
for (int i = startIndex + 1; i < nums.length; i++) {
if (nums[i] == value) return i;
}
return -1;
}
}
3.哈希破解法
在上面两次解法中我们会发现,最终影响效率的是寻找 y 的 下标 j 所耗费的时间复杂度较高
我们可以联想到Hash的查找效率非常之快达到了O(1) 而不是上述的O(n)
将数组转化为Hash结构,在java中我们知道典型的Hash的代表是Map函数,然后在进行相同的逻辑去寻找 y 的 下标 j
class Solution {
public int[] twoSum(int[] nums, int target) {
// 转化为hash结构
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
int x, y;
for (int i = 0; i < nums.length; i++) {
x = nums[i];
y = target - x;
if (map.containsKey(y)) {
return new int[]{i, map.get(y)};
}
}
return new int[0];
}
}
4.哈希破解优化版
我们可以不用一次性全部将nums的数值置入Map中之后再去统一查找,而是在每一次置入的时候去查找是否有匹配的 y 在map中.
不存在在将x 与 i 置入map中
这样可以大幅度减少相对空间复杂度
class Solution {
public int[] twoSum(int[] nums, int target) {
int x,y;
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
x = nums[i];
y = target - x;
if (map.containsKey(y)) {
return new int[]{i, map.get(y)};
}
map.put(x, i);
}
return new int[0];
}
}
每一个解决方案的衍生都是一个思考的过程,我们不应该去一味的追求解题刷题的速度,而是提高自己思维,探求未知。
如有不当之处望指出
闻道有先后,术业有专攻,如是而已 -- 《师说》