Leetcode-Two Sum

96 篇文章 0 订阅
68 篇文章 0 订阅

转自:http://www.cnblogs.com/dollarzhaole/archive/2013/06/24/3152962.html

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

 

解题思路:

(1)O(nlogn)。排序,然后两个指针一前一后。因为题中说明了只有一对答案,因此不需要考虑重复的情况。

(2)O(n)。哈希表。将每个数字放在map中,历遍数组,如果出现和数组中的某一个值相加为target的时候,break。这个方法同样适用于多组解的情况。


(1)先排序,后搜索查找

struct Node
{
    int num, pos;
};
bool cmp(Node a, Node b)
{
    return a.num < b.num;
}
class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<int> result;
        vector<Node> array;
        for (int i = 0; i < numbers.size(); i++)
        {
            Node temp;
            temp.num = numbers[i];
            temp.pos = i;
            array.push_back(temp);
        }

        sort(array.begin(), array.end(), cmp);
        for (int i = 0, j = array.size() - 1; i != j;)
        {
            int sum = array[i].num + array[j].num;
            if (sum == target)
            {
                if (array[i].pos < array[j].pos)
                {
                    result.push_back(array[i].pos + 1);
                    result.push_back(array[j].pos + 1);
                } else
                {
                    result.push_back(array[j].pos + 1);
                    result.push_back(array[i].pos + 1);
                }
                break;
            } else if (sum < target)
            {
                i++;
            } else if (sum > target)
            {
                j--;
            }
        }
        return result;
    }
};

算法中的sort的时间复杂度:http://blog.csdn.net/leo115/article/details/8654294(sort详细讲解)

stl <algorithm> 中的sort算法实现,采用快排的思想,平均的时间复杂度是 N(logN);算法中还提供了其他的集中排序函数 sort_heap()  stable_sort()  时间复杂度都在 N(logN)


(2)哈希(转自:http://blog.csdn.net/jiadebin890724/article/details/23305449

思路是循环一次,每次都判断当前数组索引位置的值在不在hashtable里,不在的话,加入进去,key为数值,value为它的索引值;接下来再在hashtable中查找(target-当前数值)这个数,利用了hashtable中查找元素时间为常数的优势,如果找到,取得他的key,记为n(此时n一定小于循环变量i,如输入2,3,4,target=6,判断2的时候4还没加载进来,所以继续循环,到4的时候,找了前边的2)。此处需要注意的是,如果数组中有重复的值出现,那么第二次出现时就不会加入到hashtable里了,比如3,4,3,6;target=6时,当循环到第二个3时,也可以得到正确结果

class Solution {
public:
    vector
   
   
    
     twoSum(vector
    
    
     
      &numbers, int target) {
        int i, sum;
        vector
     
     
      
       results;
        map
      
      
       
        hmap;
        for(i=0; i
       
       
         (numbers[i], i)); } if(hmap.count(target-numbers[i])){ int n=hmap[target-numbers[i]]; if(n 
         
 
总结:读完题首先想到的就是两层遍历法,但是显然时间复杂度太高,是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)还大的时候(在一篇博客里看到的)。



ps:自己的

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      

using namespace std;

class Solution
{
public:
    vector
       
       
        
         twoSum(vector
        
        
          & nums, int target) { int len=nums.size(); int i=0; int j=0; map 
         
           hmap; map 
          
            ::iterator iter; //有重复的值只加 第一次,第35行循环nums【i】的时候i可以从头循环到位 //所以重复的值是可以循环到-除非已经得到结果了 while(i 
           
             (nums[i],i)); //hmap[nums[i]]=i; i++; } iter=hmap.begin(); while(iter!=hmap.end()) { cout< 
            
              second<<":"< 
             
               first< 
              
                second ;//hmap[target-nums[i]]; //找到它自己 如 0+0=0,那舍弃。如果输入中有两个0也没关系,i回轮询到每个0的,尽管map里面只有一个 if(max==min) { i++; continue; } //这里if else不能省略,不能像https://code.csdn.net/snippets/656002那样,因为他的只有n==i(自己加自己)和n 
               
                 second = 0 //这时候min=3,max=0,这时max 
                
                  min) { vectorReturn.push_back(min+1); vectorReturn.push_back(max+1); return vectorReturn; } else { vectorReturn.push_back(max+1); vectorReturn.push_back(min+1); } return vectorReturn; } i++; } return vectorReturn; } private: vector 
                 
                   vectorReturn; }; int main() { vector 
                  
                    nums; nums.push_back(0); nums.push_back(4); nums.push_back(3); nums.push_back(0); Solution sl; nums=sl.twoSum(nums,0); if(nums.size()==2) cout<<"result "< 
                   
                     <<":"< 
                    
                      <<"\n"; else cout<<"not find\n"; return 0; } 
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
        
       
       
     
     
    
    
要注意重复的输入且结果就是重复输入的两数之和 map找的是自己,自己加自己的情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值