美文网首页
LeetCode刷题 1 两数之和

LeetCode刷题 1 两数之和

作者: 江湖路远_各自珍重 | 来源:发表于2018-07-06 21:16 被阅读37次

    LeetCode刷题 1 两数之和

    题目

    给定一个整数数组和一个目标值,找出数组中为目标值的两个数。

    你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

    示例

    给定 nums = [2, 7, 11, 15],target = 9

    因为 nums[0] + nums[1] = 2 + 7 = 9

    所以返回[0, 1]

    思考

    最简单、最直接的想法就是暴力的嵌套的双循环,遍历每个元素计算。空间复杂度虽然是O(1),但是时间复杂度却是O(n^2),因为对于每个元素,都试图遍历它以外的所有元素来求解,这一次循环就耗费O(n)时间。所以对于长度越长的数组来说效率越低。
    所以需要一种更有效的方法来检查数组中是否存在所需的元素。如果存在,就返回它的索引。这里可以使用哈希表。通过牺牲空间换取时间。可以将查找时间从O(n)降底到O(1),哈希表正是为此目的而构建,它支持以近似恒定的时间进行快速查找。之所以“近似”,是因为一旦出现冲突,查找时间可能退化到O(n)。只要仔细的挑选哈希函数,在哈希表中进行查找的用时应当被摊销为O(1)。
    使用哈希表的话,时间复杂度为O(n),因为查找时间缩短到了O(1)。空间复杂度为O(n)。

    解题思路

    关键点在于 nums[i] + nums[j] = target,即等于 nums[i] = target - nums[j]。可以做个哈希表,表里面存储以target - nums[j](目标元素)为键,当前索引为值。在迭代并将元素插入到表中的同时,进行检查表中是否已经存在当前元素所对应的目标元素。如果存在,即找到对应解,立即返回。

    Python实现

    Python里面的字典就是利用哈希表存储的,可以拿来直接使用。

    class Solution:
      def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if len(nums) <= 1:
          return [0, 0]
    
        d = dict()
        for i in range(len(nums)):
          if nums[i] in d:
            return [d[nums[i]], i]
          else:
            d[target - nums[i]] = i
    

    在LeetCode上跑了44ms

    C++实现

    C++的话,需要使用里面的hash_map,std里面还有map,map底层是使用红黑树存储的。查找时间复杂度是O(logn)。
    有关hash_map的介绍可以阅览《详细解说STL hash_map系列》。那么正常情况下什么时候用map,什么时候用hash_map?需要具体看应用,复杂度为常数级别O(1)的hash_map就一定比O(logn)级别的map要好,hash_map的hash函数以及解决地址冲突等都需要耗时,而且hash表是以空间效率来换取时间效率的,所以hash_map所耗内存更大。一般情况下,数据量很大的时候,可以考虑使用hash_map,可以提高查找效率。但如果需要谨慎使用内存的时候,就应该考虑使用map了。
    (2018/07/09追加,根据C++ 11标准的推荐,用unordered_map代替hash_map。关于unordered_map可以参考下面文章的介绍)

    class Solution
    {
      public:
        std::vector<int> twoSum(std::vector<int>& nums, int target)
        {
          std::unordered_map<int, int> dict;
          std::vector<int> result;
          for(int i = 0; i < nums.size(); ++i)
          {
            auto it = dict.find(nums[i]);
            if(it != dict.end())
            {
              result.push_back(dict[nums[i]]);
              result.push_back(i);
              return result;
            }
            else
            {
              dict.insert(std::pair<int, int>(target - nums[i], i));
            }
          }
          return result;
        }
    };
    

    在LeetCode上跑了8ms

    相关文章

      网友评论

          本文标题:LeetCode刷题 1 两数之和

          本文链接:https://www.haomeiwen.com/subject/jztsuftx.html