【LeetCode】Two Sum——第一次接触LeetCode

本来计划着暑假一开始就刷刷一些大公司的笔试题,没想到暑假一逛过了一个月了,还没半点儿动手的痕迹,给自己找了个欺骗自己的接口——实习太忙了。。。好吧,昨天在网上不小心看到fanfanK写的一篇博客2014校园招聘总结,里面讲的内容挺不错的,我也非常同意里面的一个观点——不要抱死一家公司不放;里面还提到了LeetCoed这个东西(一个在线题库,自带编译),也因此才有了我这边博客。离今年秋招还有1个多月的时间,LeetCode目前有151道题目,对我这个算法菜鸟来说,还真有点压力,不过没关系,那我就从最远的那一道题目开始做起吧,能做多少算多少!(我也非常认可笔试成绩的重要性,很多人一大早就开始刷题了,我也不能落后啊)


直接上题:

Two Sum

  Total Accepted: 27292  Total Submissions: 148668 My Submissions

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

刚看到这道题目的时候,我还在偷笑,哈哈,这个不难嘛。

class Solution {
public:
	vector<int> twoSum(vector<int> &numbers, int target) {
		vector<int> result;
		int size = numbers.size();
		for( int i = 0; i < size - 1; i++ ){
			//if (numbers[i] > target){//这个判断是不行的,后面那个是负数的话,相加也能等于target
			//	continue;
			//}
			for( int j = i + 1; j < size; j++ ){
				if( numbers[i] + numbers[j] == target){
					result.push_back( i+1 );
					result.push_back( j+1 );
					return result;
				}
			}
		}
		return result;
			
	}
};
以为稳稳地过了,没想到:

Submission Result: Time Limit Exceeded
纳尼,怎么?居然还有时间限制?好吧,思考了一下,难道要用到排序?不大可能啊,排序用的时间也不比这个短多少吧,而且还要记录位置的信息。没办法,只能那个了。

百度了一下,发现别人用的是map,亏了,以前还真没用过这东西。

修改后的代码:

class Solution {
public:
        twoSum(vector<int> &numbers, int target) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
            map<int, int> m;
            int sz = numbers.size();
            for(int i = 0; i < sz; ++i) {
                map<int, int>::iterator p = m.find(target - numbers[i]);
                if(p != m.end()) {
                return vector<int>({p->second + 1, i + 1});//这个是C11新加的
                m[numbers[i]] = i;
                }
            }
        };


总结:

个人脑子比较直,一看到题目就想到用双循环做,事实证明,算法题,永远不可能这么直白的。下面是某位跟我有同样经历的大神的总结:

总结:读完题首先想到的就是两层遍历法,但是显然时间复杂度太高,是O(N^2),不符合要求,于是就应该想如何降低复杂度,首先应该想将逐个比较转变为直接查找,即首先计算出 target与当前元素的差,然后在序列中寻找这个差值,这样首先就把问题简化了,而寻找的过程可以先对序列进行快排,然后二分查找,这样整体的复杂度就降低为 O(N*logN) 了;查找最快的方法是利用一个 map容器存储每个元素的索引,这样取得某个特定元素的索引只需要常数时间即可完成,这样就更快了,最多只需遍历一次序列,将元素及其索引加入map中,在遍历的过程中进行对应差值的查找,如果找到了就结束遍历,这样时间复杂度最多为 O(N),It's amazing!

        本来想用C++的hash_map,后来发现STL并没有这个容器,貌似需要自己实现代码才能用,遂用map了,map底层使用红黑树实现的,所以它的查找时间是O(logN),略逊于hash_map,但是这不是绝对的,hash_map虽然理论上是O(N),其实他还有计算hash值的时间消耗,也存在时间比O(logN)还大的时候(在一篇博客里看到的)。还要注意在leetcode里提交时要把cout的代码注释掉,否则可能会导致评判结果出错,本题还要注意就是map的count函数用于查找某个key是否存在,存在返回1,否则返回0;根据某个key取得其在map中的value值的方法是直接用map[key]即可。

撇开笔试不管,个人觉得做编程题,最大的收获就是对于相同的问题,看看别人(特别是大神)是这么做的,学习别人的解题思路。


第一次接触LeetCode的收获:

  1. map的使用
  2. vector的C11赋值方法


再接再厉!





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值