题目描述: 1. 两数之和 - 力扣(LeetCode)
审题分析: 仔细分析题干,题目中存在较多的隐藏条件 : 第一点是结果是两个整数;第二点是一定存在结果;第三点是由于结果唯一性的要求,不可能出现多组解以及(target = 6 , nums中含有3个3的情况)
解题思路分析 : 首先,因为题目中涉及到匹配查询的问题,第一反应是hash表的查询复杂度均为o(1) , 所以考虑建立一个map , 然后循环遍历数组并且map.put(nums(i),i) ,让数组全部转换到map表中,然后遍历map表中的key值,并采用map.containsKey(target-key) 的方式进行搜寻 ,代码下所示.
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> nummap = new HashMap<>();
int[] result = new int[2];
for(int i=0 ; i<nums.length ; i++)
nummap.put(nums[i],i);
for(Integer key : nummap.keySet())
{
if(nummap.containsKey(target-key))
{
result[0] = nummap.get(key);
result[1] = nummap.get(target-key);
return result;
}
}
}
}
但是上述代码出现两个问题,第一个问题是hash表有自动去重功能,会导致(targets=6 nums=[3,3,1]情况)出错,; 第二个问题是map的containsKey的方法在key=target-key的情况下重复检测同一个set对;
针对上面的问题,第一个思路是补缺问题, 放弃,复杂度大大提升;第二个思路是用value作为遍历对象,解决了去重的问题 , 但是涉及到一个由value得到key的过程,复杂度大大提升; 第三个思路是,用cpp数据结构中的另外一个map结构,如下图所示,放弃,仍然存在问题二 ; 第四个思路,既然存在重复检测的问题和第一个问题出现的特殊情况,那是否能考虑不先将数组转成map,而是边检测边转入,这样子既可以避免重复检测同一个元素,又能在出现(targets=6 nums=[3,3,1]情况)情况时,在没存入第二个3的情况下进行检测, 成功代码如下:
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> nummap = new HashMap<>();
int[] result = new int[2];
for(int i=0 ; i<nums.length ; i++)
{
if(nummap.containsKey(target-nums[i]))
{
result[0] = nummap.get(target-nums[i]);
result[1] = i;
return result;
}
nummap.put(nums[i],i);
}
throw new IllegalArgumentException("输入错误,无正确答案");
}
}