LeetCode 两数之和(4种方法 C、C++ 实现)

这篇博客介绍了LeetCode两数之和问题的四种解决方案,包括使用两遍hash算法、一遍hash算法、暴力求解和C语言方法。重点讲解了如何利用map数据结构高效地寻找目标值的数组下标,并对比了不同方法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

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

示例

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

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

所以返回 [0,1][0, 1][0,1]

map的使用方法

1、map是标准的关联式容器,在#include<map>头文件中。一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。

#include<map>
#include<algorithm> //这个头文件最好也加上
map<int,string> mymap1,mymap2;

2、map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。

mymap1.insert(pair<int,string>(1,"C++"));
mymap2.insert(pair<int,string>(2,"Java"));

也可以用insert函数插入value_type数据

mymap1.insert(map<int,string>::value_type(1,"C++"));
mymap2.insert(map<int,string>::value_type(2,"Java"));

3、map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。

4、map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。

mymap1[1] = "C++";
mymap2[2] = "Java";

以上三种用法,都可以实现数据的插入,但还是有所区别,第一种和第二种是一样的,用insert函数插入数据在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式可以覆盖以前该关键字对应的值。

5、查找map中的元素,第一种,用count函数来判定关键字是否存在,其缺点是无法定位数据出现位置。由于map的一对一的映射关系,就决定了count函数的返回值只有两个,存在返回1,不存在返回0;

mymap1.count(1);//存在key为1的键值,返回1,不存在,返回0

第二种:用find函数来定位数据出现位置,它返回的是数据位置的一个迭代器,如果没有找到map中的数据,返回的迭代器为map中的end()。

mymap1.find(1); // 返回key为1的数值的迭代器的位置 不存在 返回end()

下面将分别从调用两遍哈希算法、调用一遍哈希算法、暴力求解、C语言解法这四种方法来解答此题。

代码实现

1、使用两遍hash算法求解

先将每个元素的键值对赋值好再进行比较,由于题目要求返回两个数的数组下标,所以nums数组的元素值为map中的key值,元素所对应的数组下标为map中的value值,这与正常思路是相反的。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int ,int> mymap;
        for(int i = 0; i < nums.size(); i++)
        {
            mymap[nums[i]] = i; // 反过来存 和正常思路相反
        }
        for(int i = 0; i < nums.size(); i++)
        {
            if(mymap.find(target - nums[i]) != mymap.end() && mymap[target - nums[i]] != i)
            {
                return {i, mymap[target - nums[i]]};
            }
        }
        return {};
    }
};

2、使用一遍hash算法求解

在mymap已有的赋值元素中找到与nums[i]nums[i]nums[i]之和为targettargettarget的值,因为指针iii一直在mymap所有元素的后序,所以返回的数组下标序列中,iii应该在后面。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int> mymap;
        for(int i=0;i<nums.size();i++)
        {
            if(mymap.find(target-nums[i])!=mymap.end())//mymap中存在对应的键值
                return {mymap[target-nums[i]],i};
            mymap[nums[i]]=i;  //向map中添加元素
        }
        return {};
    }
};

这两种方法本质上没有明显的区别,时间复杂度均为O(n)O(n)O(n)

3、暴力求解

该方法实现的时间复杂度要高与前两种,为O(n2)O(n^2)O(n2),但是思考起来比较容易。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for(int i=0; i<nums.size() - 1; i++)
        	for(int j = i + 1; j < len; j++)
            	if(nums[i] + nums[j] == target)
            		return {i,j};
       return {};
    }
};

4、C语言方法

这是C语言的解答,时间复杂度为O(n2)O(n^2)O(n2)

int* twoSum(int* nums, int numsSize, int target) {
    int i,j;
    int *result=NULL;
    for(i = 0; i < numsSize - 1; i++)
    {
        for(j = i + 1; j < numsSize; j++)
        {
            if(nums[i] + nums[j] == target)
            {
                 result = (int*)malloc(sizeof(int) * 2);
                 result[0] = i;
                 result[1] = j;
                 return result;
            }
        }
    }
    return result;
}

永远不要说自己有多么爱动脑,学习多么刻苦,因为网上总会有比你更新颖的,思路更清晰的解答方法,他们会比你更刻苦或者是更聪明,甚至是两者兼备。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值