zoukankan      html  css  js  c++  java
  • LeetCode:Two Sum

    题目链接

    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

    注意:元素可能有重复

    最简单的做法就是一个两重循环,时间复杂度是O(n^2),下面提供两种更高效的解法

    算法1:

    将数组的数组映射到哈希表,key是元素的值,value是该值在数组中的索引。考虑到数组中元素有重复,我们使用STL中的unordered_multimap, 它可以允许重复的key存在。映射以后,对于数组中的某个元素num,我们只要在哈希表中查找num2 = target-num。需要注意的是在哈希表中找到了num2,并不一定代表找到了题目要求的两个数,比如对于数组2 7 11 15,target = 4,当num = 2时,num2 = target-num = 2,此时num2可以在哈希表中找到,但是num和num2指向的是同一个元素。因此当num2 = num时,在哈希表找到num2的同时,还需要保证哈希表中num2的个数>=2。

    该算法时间复杂度为O(n)

     1 class Solution {
     2 public:
     3     vector<int> twoSum(vector<int> &numbers, int target) {
     4         int n = numbers.size();
     5         vector<int> res;
     6         unordered_multimap<int, int> umap;
     7         for(int i = 0; i < n; i++)
     8             umap.insert(make_pair(numbers[i], i));
     9         for(int i = 0; i < n; i++)
    10         {
    11             auto range = umap.equal_range(target - numbers[i]);
    12             if(range.first != umap.end())//found
    13             {
    14                 if(numbers[i] != target - numbers[i])
    15                 {
    16                     auto range2 = umap.equal_range(numbers[i]);
    17                     res.push_back(min(range.first->second, range2.first->second) + 1);
    18                     res.push_back(max(range.first->second, range2.first->second) + 1);
    19                 }
    20                 else
    21                 {
    22                     auto ite = ++(range.first);
    23                     if(ite != range.second)
    24                     {
    25                         auto range2 = umap.equal_range(numbers[i]);
    26                         res.push_back(min(ite->second, range2.first->second) + 1);
    27                         res.push_back(max(ite->second, range2.first->second) + 1);
    28                     }
    29                 }
    30             }
    31         }
    32         return res;
    33     }
    34 };

    算法2:

    首先对数组按小到大排序,然后设定两个指针head、tail分别指向排序好的数组的首尾:                                     本文地址

    • 如果两个指针对应的元素和等于target,那么找到了
    • 如果两个指针对应的元素和小于target,那么需要增加和的大小,则把head指针向后移动
    • 如果两个指针对应的元素和大于target,那么需要减少和的大小,则把tail指针向前移动
    • head赶上tail指针时,结束

    由于本题中需要返回最后找到的数对的索引,因此,排序是我们不移动原来数组的元素,只是把元素的的索引放到一个新的数组,对这个新的索引数组排序

     1 class Solution {
     2 private:
     3     static vector<int> *numbersCopy;
     4     static bool cmp(int idx1, int idx2)
     5     {
     6         return (*numbersCopy)[idx1] < (*numbersCopy)[idx2];
     7     }
     8 public:
     9     vector<int> twoSum(vector<int> &numbers, int target) {
    10         numbersCopy = &numbers;
    11         int n = numbers.size();
    12         vector<int> res;
    13         vector<int> idx(n);
    14         for(int i = 0; i < n; i++)
    15             idx[i] = i;
    16         sort(idx.begin(), idx.end(), Solution::cmp);
    17         
    18         int head = 0, tail = n-1;
    19         while(head < tail)
    20         {
    21             if(numbers[idx[head]] + numbers[idx[tail]] < target)
    22                 head++;
    23             else if(numbers[idx[head]] + numbers[idx[tail]] > target)
    24                 tail--;
    25             else //found
    26             {
    27                 res.push_back(min(idx[head], idx[tail]) + 1);
    28                 res.push_back(max(idx[head], idx[tail]) + 1);
    29                 break;
    30             }
    31         }
    32         
    33         return res;
    34     }
    35 };
    36 vector<int> * Solution::numbersCopy = NULL;

    推荐参考博客:

    程序员编程艺术:第五章、寻找满足和为定值的两个或多个数

    求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)

    编程之美2.12-快速寻找满足条件的两个数

    【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3647244.html

  • 相关阅读:
    为什么你应该(从现在开始就)写博客
    ASP.net 中使用Flexigrid详细教程之二直接使用数据库数据(有图有真相)
    保护眼睛的方法 (眼睛累了吗 来看看吧)
    程序员不如快递员?
    项目管理界面
    地址栏射击游戏!对,你没看错,就是在地址栏上玩的游戏,有图有真相!
    书写是为了更好的思考
    IT人员如何找到自己的时间?
    std::mem_fun_ref,mem_fun1_ref分析
    __declspec(selectany) 的作用是什么
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3647244.html
Copyright © 2011-2022 走看看