代码随想录二刷 | 哈希表 |两数之和

代码随想录二刷 | 哈希表 |两数之和

  • 题目描述
  • 解题思路 & 代码实现

题目描述

1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

解题思路 & 代码实现

本题需要一个集合来存放遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是是否出现在这个集合。

本题不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key-value结构来存放,key来存元素,value来存下标,那么使用map正合适。

再来看一下使用数组和set来做哈希法的局限。

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断 y 是否存在而且还要记录 y 的下标位置,因为要返回 x 和 y 的下标。所以set 也不能用。

此时就要选择另一种数据结构:map ,map是一种key-value的存储结构,可以用key保存数值,用value保存数值所在的下标。这道题目中并不需要key有序,选择std::unordered_map 效率更高。

接下来需要明确两点:

  • map用来做什么
  • map中key和value分别表示什么

map 用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

判断元素是否出现,这个元素就要作为key,所以数组中的元素作为keykey对应的就是valuevalue用来存下标。

所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对;如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

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

时间复杂度:O(n)
空间复杂度:O(n)

你可能感兴趣的:(代码随想录二刷,c++,算法)