【LeetCode】TwoSum-求数组中两个数之和等于指定目标的加数下标
TwoSum 题目描述
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example
Given nums = [2, 7, 11, 15], target = 9,
Because nums[ 0 ] + nums[ 1 ] = 2 + 7 = 9,
return [0, 1].
解决思路
思路一:
假设数组是按序排列的,那么就算是暴力搜索,疯狂遍历也可以节省很多时间,因为
nums[0]
n
u
m
s
[
0
]
是数组中的最小值,先取
nums[0]
n
u
m
s
[
0
]
,然后开始遍历,若出现
nums[0]+nums[i]>target
n
u
m
s
[
0
]
+
n
u
m
s
[
i
]
>
t
a
r
g
e
t
时,显然下标大于
i
i
的数无需再遍历。按着这个思路,一开始取数组中,最大的数和最小的数,分为 3 个判断:
: 让小的数变大,继续遍历,
i+1
i
+
1
;
nums[i]+nums[j]<target,i>j
n
u
m
s
[
i
]
+
n
u
m
s
[
j
]
<
t
a
r
g
e
t
,
i
>
j
: 让大的数变小,继续遍历,
j−−
j
−
−
;
nums[i]+nums[j]<target,i=j
n
u
m
s
[
i
]
+
n
u
m
s
[
j
]
<
t
a
r
g
e
t
,
i
=
j
: 得到结果
思路二:
目标要找到:
A+B=target
A
+
B
=
t
a
r
g
e
t
从第一个开始找,
nums[0]
n
u
m
s
[
0
]
要满足要求,就希望数组中有另一个数,它的数值等于
target−nums[0]
t
a
r
g
e
t
−
n
u
m
s
[
0
]
,因此利用哈希表的字典查询功能,查询数组中是否有满足要求的,若有,则读取下标,结束遍历;否则继续遍历。
所以在简单的遍历思想上,加一点点小处理就可以解决了。不过这种方法每次运行的时间可能都不一样,因为若满足要求的其中一个数下标很靠前,那运行的速度就会快;若满足要求的两个数的下标都很靠后,那就相对比较费时。
下面附上完整代码:
代码块
思路一:
import java.util.Arrays;
class Solution {
public int[] twoSum(int[] nums, int target) {
int head = 0,tail = nums.length-1, flag = 0;
int[] output = new int[2];
int[] temp = new int[nums.length];
System.arraycopy(nums,0,temp,0,nums.length);
Arrays.sort(temp); //对数组排序
while(head<tail)
{
if(target > (temp[head]+temp[tail]))
{
head++;
}
else if(target < (temp[head]+temp[tail]))
{
tail--;
}
else
{
for (int i = 0; i < nums.length; i++){
if(nums[i] == temp[head] && flag == 0)
//flag 用于避免两加数相等时找到的下标一样
{
output[0] = i;
flag = 1;
}
else if(nums[i] == temp[tail] && i!= output[0])
{
output[1] = i;
}
}
break;
}
}
return output;
}
}
完成思路一的代码的过程中遇到了以下问题:
(1)创建临时数组 temp 时直接赋值 int[] temp = nums
,这种赋值是地址上的赋值,因此执行sort(temp)
时,改变的也是 nums 数组。后面查询过后,可以采用数组的复制,完成仅仅是数值的复制。数组的复制也有多种方法,最简单的 for 循环遍历赋值,以下列出 Java 中可用的复制方法:
- for 循环方法
- System.arraycopy()方法
- Arrays.copyOf()方法
- Object.clone()方法
代码示例:
int[] nums = {3,2,4}; // 原数组
int[] temp = new int[nums.length]; // 复制数组
// 方法1:
for(int i = 0; i<nums.length;i++)
{
temp[i]=nums[i];
}
// 方法2:
// 参数说明:arraycopy(原数组,原书序需复制的起始位置,复制数组,复制数组放置的起始位置,复制长度)
System.arraycopy(nums, 0, temp, 0, nums.length);
// 方法3:
temp = Arrays.copyOf(nums, nums.length);
// 方法4:
temp = nums.clone();
以上方法及具体的优劣对比参考:
《Java中数组复制的几种方法 》:www.cnblogs.com/zhengbin/p/5671403.html
(2)在最后一步找回对应原数组的下标时,我一直想尽量少写代码(不会写+懒 orz),所以一开始直接使用output[0] = Arrays.binarySearch(nums,temp[head])
查询数组下标。当然是因为有bug,所以迫使我去改了,不然没办法 Accepted 呀。错误的原因是 Arrays.binarySearch(数组,目标数值)
原理是使用二分法查询找出下标。二分法一般用于排序后的数组,对于 nums 原数组是没有排序的,因此查询的结果不稳定,会出错。
具体可看:
《JAVA之数组查询binarySearch()方法详解》:https://blog.csdn.net/a1b2c3d4123456/article/details/51097161
思路二:
import java.util.Arrays;
class Solution {
public int[] twoSum(int[] nums, int target) {
int index[] = {0,0};
HashMap<Integer, Integer> num = new HashMap<Integer,Integer>(); //创建哈希表
for(int i=0;i<nums.length;i++) //初始化哈希表
{
num.put(nums[i], i);
}
for(int i=0;i<nums.length;i++)
{
int temp = target-nums[i]; // 求出另一个期望加数temp
if(num.containsKey(temp)&&i<num.get(temp))
//判断哈希表中是否含有与temp相等的,若是则目标找到
{
index[0] = i;
index[1] = num.get(temp);
break;
}
}
return index;
}
}
欢迎大家有更好的方法讨论分享~
小白初学编程 > <