LeetCode-NO.01两数之和(一题多解-C++)


题目描述:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

Sol-1.暴力法

作为一名刚入门的初学者,这是我在LeetCode上遇到的第一道题,老话说的好,来个开门红,新话说得妙,我想要一个好的开始,然并卵,我唯一能想到的方法就是暴力法,别无他法,我也很无奈…不过没事,在自我虐待中成长。
思路:

  • 1、暴力法就是两个for循环嵌套,分别把数组遍历两次,时间复杂度是O(n^2),贼高。
  • 2、当遍历到nums[i] +nums[j]等于目标值target,则就返回两个元素的数组下标 i, j,没有找到就返回空。
    注:暴力法通常没啥技术含量,要多多接触有深度,可以装逼的算法。如Sol-2。
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for(int i = 0; i < nums.size(); i++)
        {
            for(int j = i+1; j < nums.size(); j++)
            {
                if(target == nums[j] + nums[i])
                {
                   return {i,j};
                }
                }
        }
        return {};
    }
};

提交记录:在这里插入图片描述

Sol-2.两遍哈希表

第二个解决方法就需要读者有一定的C++STL(Standard Template Library的简称,中文名标准模板库)的知识以及对哈希算法有一定的了解,不然可能你看代码如天书。算法虐我千百遍,我对算法如初恋。
作为一个大学四年不知道干了啥的学渣来说,我花了将近两周的时间才把map容器和哈希表的一些原理,用法,函数搞懂了一些,当然每天花的时间不多,就晚上学一下,因为白天要上班。可能是我太菜了…当然,当我能用哈希表解决这个问题时,就如我辛勤种植的果实终于可以收获,这种feel倍爽!
map:map是STL中的一种关联容器,它提供一种一对一的数据处理能力,容器中的每一个元素都是由一个键值和一个数据值组成的,也就是一个键值对(Key-Value)的容器。
思路:

  • 1、我们是要得到nums[i]+nums[j] = target的下标i , j;
  • 2、先把数组元素以键值key为nums[i],value为i插入map容器;
  • 3、然后遍历数组,如果在map容器中找到满足题目要求的另一值 res(nums[j] = target - nums[i]) 的Key,则返回它们各自的下标。
    注:代码中的难点有注释。
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
       map<int,int> Map;
       vector<int> v1;
       for(int i = 0; i < nums.size(); i++) 
           Map[nums[i]] = i;//把数组元素以键值为nums[i],value为i插入map容器
        for(int j = 0; j < nums.size(); j++)
        {
            int res = target - nums[j];
            if(Map.count(res) && Map[res] != j) //另一个需要的值res存在于map容器且不是nums[j]本身
            {
                v1.push_back(j);
                v1.push_back(Map[res]);//map容器基于运算符[]通过访问键值key来获得value
                return v1;
            }
        }
        return v1;
    }
};

注:下图与暴力法相比,所用时间有大幅度减少,效率明显提高。
在这里插入图片描述

Sol-3.一遍哈希表

思路:

  • 1、首先在map容器中插入键值对之前,先查找map容器中是否有key为nums[i],若有则返回nums[i]在数组中的下标,以及nums[i]在容器中的value即下标(nums[i]在容器中的键值即为对应元素的目标元素(target - nums[i]));
  • 2、若无,则将对应元素的目标元素(target - nums[i])的键值对插入map容器中,遍历数组中下一个元素,一直循环直至找到或数组中没有这两个目标元素。
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
       map<int,int> hash_map;
        int i = 0;
        while(i < nums.size())
        {
            if(hash_map.find(nums[i]) != hash_map.end())
                return {hash_map[nums[i]], i};
            hash_map[target - nums[i]] = i;
            i++;
        }
        return {};
    }
};

注:很显然一遍哈希的效率最高,当然难度也最大,其实这个不断优化的过程就是一步一步地在向更高的困难向挑战,过程很虐人,但是结果很爽。我很enjoy it!希望你们也一样。
在这里插入图片描述

完整代码实现(含主函数测试代码)

Why:当用这三种方法做完这个题目时,我很想自己来实现这个测试案例,主要是想看在map容器中,如果遇到结果等于两个重复数字之和的时候,就是关键字key相同时,是否出错,于是在网上搜了挺久,然后没有相关的代码实现,于是我就自己写了一下,如下:
实例:
给定nums为{2,3,3,,17},target = 6
nums[1] + nums[2] =3 + 3 =6
故结果应返回{1,2}

#include<iostream>
#include<map>
#include<vector>
using namespace std;
class Sol {
public:
	vector<int> twoSum(vector<int>& nums, int target) {
		map<int, int> hash_map;
		int i = 0;
		while (i < nums.size())
		{
			if (hash_map.find(nums[i]) != hash_map.end())
				return { hash_map[nums[i]], i };
			hash_map[target - nums[i]] = i;
			i++;
		}
		return {};

	}
};
int main()
{
	vector<int> array = { 2,3,3,17 };
	vector<int> res;
	int tar = 6;
	Sol test;
	res = test.twoSum(array, tar);
	for (int j = 0; j < res.size(); j++)
	cout << res[j] << endl;
	system("pause");
	return 0;
}

在这里插入图片描述
Explanation:因为map容器中关键字是不允许重复的,而当遇到结果为重复的数字之和时(在此为相同关键字),因为不论是两遍哈希还是一遍哈希,在遇到第二个相同关键字时,并没有把它插入map容器,而是直接就返回结果了,所以map容器中并没有出现重复关键字,也就不会出现错误。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值