• 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

  • 相关阅读:
    intel 蓝牙驱动安装时报错
    H310C,B365,M.2 NVME SSD,USB3.0,安装 WIN7 64 位
    C# .NET 判断输入的字符串是否只包含数字和英文字母
    squid http,https, 代理,默认端口3128
    C# .net mvc web api 返回 json 内容,过滤值为null的属性
    centos7安装python-3.5
    systemctl命令完全指南
    Centos7中systemctl命令详解
    Python if 和 for 的多种写法
    CentOS 7.0,启用iptables防火墙
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3647244.html
Copyright © 2020-2023  润新知