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

本來計劃着暑假一開始就刷刷一些大公司的筆試題,沒想到暑假一逛過了一個月了,還沒半點兒動手的痕跡,給自己找了個欺騙自己的接口——實習太忙了。。。好吧,昨天在網上不小心看到fanfanK寫的一篇博客2014校園招聘總結,裏面講的內容挺不錯的,我也非常同意裏面的一個觀點——不要抱死一家公司不放;裏面還提到了LeetCoed這個東西(一個在線題庫,自帶編譯),也因此纔有了我這邊博客。離今年秋招還有1個多月的時間,LeetCode目前有151道題目,對我這個算法菜鳥來說,還真有點壓力,不過沒關係,那我就從最遠的那一道題目開始做起吧,能做多少算多少!(我也非常認可筆試成績的重要性,很多人一大早就開始刷題了,我也不能落後啊)


直接上題:

Two Sum

 Total Accepted: 27292 Total Submissions: 148668My 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賦值方法


再接再厲!





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章