two sum

two-sum

https://www.nowcoder.com/questionTerminal/20ef0972485e41019e39543e8e895b7f

题目描述:

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].

题目中的陷阱:

要求返回两个数的下标不是两个数本身;
不可使用一个数两次;比如[2,7,5,5], target=10, 返回[2,2]错误, 应该返回[2,3]

解法1:暴力遍历(Brute Force)

思路简单,第一层遍历每个数,在遍历每个数的同时,遍历其他的数是不是他的补(target-self, complement)

class Solution {
    // 最简单的方法,就是从第一个数n1开始遍历,找到(target-n1)的数的下标;
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        // 返回数组,记录两个下标
        vector<int> res {0,0};
        for(int i=0; i<numbers.size(); i++){
            for(int j=i+1; j<numbers.size(); j++){
                if( numbers[j] == (target-numbers[i]) ){
                    res[0] = i+1;
                    res[1] = j+1;
                    return res;
                }
            }
        }
        throw invalid_argument("No two sum solution");
    }
};

复杂度:
时间复杂度:O(nˆ2)
空间复杂度: O(1)

解法2:哈希表(Two-pass Hash Table)

为了改善时间复杂度,我们需要一种高效的方便来查询complement是否在数组中;也就是说,一旦complement存在,我们就要知道它的下标,那么什么结构能方便快速的映射数据和他的下标?Hash Table
在c++中,无序hash table的查询时间都是O(1),这个是非常强悍的,也正是我们需要的。解题思路也就明朗了,我们需要两个非嵌套的循环,第一次遍历,我们建立查询表,把数组元素和他们的index建立hash table,通过数据可以map到下标:vale => index
第二次遍历,我们检查每个元素的补(complement = target-numbers[i]),是否存在在table中,一定要注意的是,complement不可以是number[i]本身!,在第一种解法中,无需担心这一点,因为解法一的嵌套循环每次从外层嵌套的index+1开始。

class Solution {
    // 最简单的方法,就是从第一个数n1开始遍历,找到(target-n1)的数的下标;
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        // 返回数组,记录两个下标
        vector<int> res ;
        unordered_map<int, int> mymap;
        // 建立hash table array's value=> array's index
        for(int i=0; i<numbers.size(); i++){
            mymap[numbers[i]] = i;
        }
        // 第二次遍历,查询是否存在当前数的complement在hash table中
        for(int i=0; i<numbers.size(); i++){
            int complement = target - numbers[i];
            if(mymap.count(complement)!=0 && mymap.at(complement)!=i){
                res = {i+1, mymap.at(complement)+1};
                return res;
            }
        }
        throw invalid_argument("No two sum solution");
    }
};

特别注意:

第二种方法中,在c++的map函数的insert只是插入新的元素,不会更新元素的,比如:

    myMap.insert("a", "apple"     );
    myMap.insert("b", "bannana"   );
    myMap.insert("c", "cherry"    );
    myMap.insert("c", "clementine");

最后的表是:"a"=>"apple"; "b"=>"bannana"; "c"=>"cherry" 坑爹啊!这里一定要用operator[ ]才有改的操作;所有这里会有错误,在这个例子下[0,3,4,0] target=0:
0=>0, 3=>1, 4=>2,在第一次遍历的时候,complement为0,对应的i=0,table中的i=0,不成立,直到i=3的时候,查到complement为index=0;因此在用insert没有更新表的情况下,答案是[3,0],而正确的答案是[0,3];
用[ ]去添加元素的话,就会有更新的效果,也会得到正确的答案;在c++17中有新的操作纠正了insert的操作;

  std::map<std::string, std::string> myMap;
    myMap.insert_or_assign("a", "apple"     );
    myMap.insert_or_assign("b", "bannana"   );
    myMap.insert_or_assign("c", "cherry"    );
    myMap.insert_or_assign("c", "clementine");

输出:
a : apple
b : bannana
c : clementine

全部评论
这句话的意思是抛出异常,因为可能找不到正确的答案,这个和测试集有关,实际做题的时候可以不用写这句话,把`return res`放在for循环的外面,写在最后一行就可以了,报错的原因可能是`missing return statement`
1 回复 分享
发布于 2020-12-05 22:47
throw invalid_argument("No two sum solution"); 这一句有什么用,我发现这一句注释掉,会让牛客网报错
点赞 回复 分享
发布于 2020-12-05 21:51
哈希表的话如果存在负数就行不通了吧
点赞 回复 分享
发布于 2021-01-10 16:21

相关推荐

秋招进行到现在终于能写总结了。完全没想到战线会拉这么长,过程会如此狼狈,不过更应该怪自己太菜了。好在所有的运气都用在了最后,也是有个去处。背景:双2本硕科班,无竞赛,本科一段研究所实习,硕士一段大厂暑期实习但无转正。技术栈是C++&nbsp;&amp;&nbsp;Golang,实习是客户端音视频(而且是鸿蒙端开发),简历两个C++项目一个Golang项目。主要投递岗位:后端,cpp软开,游戏服务端,测开,以及一些不拘泥于Java的岗位。从8月起总共投递123家公司,笔试数不清了,约面大约30家。offer/oc/意向:友塔游戏(第一个offer,面试体验很好,就是给钱好少南瑞继保(计算机科班点击就送(限男生),不...
乡土丁真真:佬很厉害,羡慕~虽然我还没有到校招的时候,也想讲一下自己的看法:我觉得不是CPP的问题,佬的背书双2,技术栈加了GO,有两段实习。投了123,面了30.拿到11个offer。这个数据已经很耀眼了。这不也是CPP带来的吗?当然也不止是CPP。至少来说在这个方向努力过的也会有好的结果和选择。同等学历和项目选java就会有更好的吗?我个人持疑问态度。当然CPP在方向选择上确实让人头大,但是我觉得能上岸,至于最后做什么方向,在我看来并不重要。至于CPP特殊,有岗位方向的随机性,java不是不挑方向,只是没得选而已。也希望自己以后校招的时候能offer满满
点赞 评论 收藏
分享
美丽的查理斯不讲武德:包kpi的啊,感觉虾皮一点hc都没有
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
21
收藏
分享
牛客网
牛客企业服务