• 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

  • 相关阅读:
    <Redis开发与运维> 阅读笔记
    请求行,请求头,请求体详解
    char 与 varchar 的区别
    python字符串的常用方法。
    快速排序的代码及原理
    C#之Dictionary源码
    C#中构造函数
    U3D——单例模式的用法
    U3D学习——设置VS2019作为开发工具
    U3D学习——脚本运行周期
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3647244.html
Copyright © 2020-2023  润新知