您现在的位置是:首页 >技术交流 >leetcode第一题 :两数之和网站首页技术交流

leetcode第一题 :两数之和

杰哥的代码 2024-07-24 06:01:03
简介leetcode第一题 :两数之和

一,题目描述

这里直接贴的leetcode中的题目(哈哈哈);

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

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

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

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

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

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

这里有三个案例。。。

二,算法思路

毫无疑问,,对于一般解法,,,我们肯定会遍历两边数组,,,来一个一个找,,对于第一个循环的遍历,,是没有方法去除的,,,所以,,想要优化算法只能降低查找的时间复杂度,,这里就用的哈希表来降低查找的时间复杂度。。

这里先说明一下,这里的解法只代表了我自己的思路,关于**“两数之和”**的一般解法,大家如果有需要的话可以看看其他博主的文章,这里只讲一下效率比较高的哈希表解法。。。。哈哈哈

1,哈希表的相关说明

哈希表是数据结构的一种,是一种散列表,,,这种结构更加便于数据的查找,查找速度会更加快,,,

但是,显而易见的是,虽然哈希表会让算法的时间复杂度更小,但是占用的空间会更多,,,就比如这题,,,用一般解法的话,时间复杂度是O(n2),空间使用是O(1), ,,但使用哈希表之后时间复杂度变为O(n), 空间复杂度变为O(n)。。。典型的空间换时间解法。。。

因此,哈希表还是比较吃空间的。。。哈哈。。

2,哈希算法

在讲哈希算法之前,不知道大家有没有了解过,,,桶排序,,,在我看来,桶排序也是哈希表的一般应用,,对于一般的排序,,,无论是快排,归并排序。。。或者其他排序算法。。都是通过两两交换将特定的元素换到前面,,,,但是桶排序,,不一样,,,下面先给出例子,,,

将数组里面的所存的值,,,变为上标,,然后变为一个判定数组,,,如果原输入的数组中存在这个值,,,就将这个数值对应出现的次数一。。。
在这里插入图片描述
如图,,这里面就差不多是桶排序,,,这里选的数值比较小,,可知在数据范围不是很大的情况下,,,用这种排序所得的时间复杂度就是O(n)的,,不过用到了辅助空间。。。。

而在数据范围很大,,,而输入范围不是很大的。。。情况下怎么解决呢?,,,就比如设置的数值范围为109,而数据的总数不过10^4,,,这样的话前面的桶排序的用发,,,就不是特别好使了,,,因为消耗的空间实在是太大了,,,这时候就出现了哈希函数,,,,

哈希函数,,,按照我的理解就是,,通过一个函数将,,,输入的值转化为一个数组上标,,,在将这个值存在其中,,,下面针对这个题目举个例子:

如图,,先开辟一个数组,,大小的话大于取模值就行,,,不要问我为什么,动动你聪明的脑瓜想想,,这里面的编号我没排序,,感觉这样的话会更清晰,,,这样的话在查找的时候,,,直接对查找值取模就可以得到相应的答案。。。
在这里插入图片描述
这样就的话就可以将数值的范围变为输入值的数目

但是,,这里还有一个问题,,当出现两个数取模的得到的值相同怎么办?,,,这就是哈希算法中的数据冲突问题,,那如何解决冲突问题呢??这里只提供一个方法,,,毕竟讲题解,,不是讲哈希表,,哈哈,,如下图:
在这里插入图片描述
这里面的输入值对10007取模得到的值都是3245,,,所以不可能将全部的值都加到3245上,,,因此我们我们将冲突的数值向后移,,,也就是出现冲突的值,,全部向后移,,直到不出现冲突为止,,,这是解决冲突的一种方法,,还有很多其他的方法,,,大家感兴趣可以去搜搜,,,

还有,,选取的,,取模的,,数值的最好是素数,,这个是通过数学证明得来的最能降低数组冲突的方式,,,大家感兴趣可以去搜搜,,,

3,题目讲解

先画个流程图,,,
在这里插入图片描述
如图,,这题相对还是比较简单的,,求两数之和,,无非就是,,对每一个数看看是否有另一个数与其相加能得到,,,目标值,,

这里主要是构建哈希表,,,

1、对于每一个输入值,,先将目标值与其的差值处理到哈希表中,,

2、在对于每一个输入值,,通过哈希表的查找,,看看是否能找到这个输入值,,找到这个输入值,,就代表有差值与这个值相等,,,也就代表有其他的输入值也这个相加等于目标值。。下面就是代码,,,

三,题解代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        const int N = 100007; //对于数据范围,这是10000以上的最小的素数
        const int INF = 0x3f3f3f3f;

        int judge[N];//定义的哈希表
        int judge1[N];//这个表存的是对应的元数组的下标
        memset(judge, INF, sizeof(judge));//初始化
        memset(judge1, INF, sizeof(judge));
        
        vector<int> res;
        //第一步:将每个元素的被减值存入到哈希表中
        for (int i = 0; i < nums.size(); i++)
       {
       //这部处理稍微看看,a是代表的寻找的哈希表中的数组编号,。,想想为什么这么写,,,
        int a = ((target - nums[i] ) % N + N) % N;
        while (judge[a] != INF) { a++, a %= N; }
        judge[a] = target - nums[i];
        judge1[a] = i;
       }
     //第二步:对于每个元素,看看哈希表中出现该值
    for (int i = 0; i < nums.size(); i++)
    {
        int t = 0;
        int a = ((nums[i] ) % N + N) % N;
        while (judge[a] != INF)
        {
            if (judge[a] == nums[i] && i != judge1[a])
            {
               res.push_back(i);
               res.push_back(judge1[a]);
                t = 1;
                break;
            }
            a ++;
            a %= N;
        }
        if (t) break;
    }
        return res;
    }
};

这是leetcode的代码,,,

#include <iostream>
#include <cstring>

using namespace std;

const int N = 100007;
const int INF = 0x3f3f3f3f;

int judge[N] ;
int judge1[N];

int nums[N];
int target;
int n;

int main()
{
    cin >> n >> target;
    memset(judge, INF, sizeof(judge));
    for (int i = 0; i < n; i++) cin >> nums[i];

    for (int i = 0; i < n; i++)
    {
        int a = ((target - nums[i] ) % N + N) % N;
        while (judge[a] != INF) { a++, a %= N; }
        judge[a] = target - nums[i];
        judge1[a] = i;
    }

    for (int i = 0; i < n; i++)
    {
        int t = 0;
        int a = ((nums[i] ) % N + N) % N;
        while (judge[a] != INF)
        {
            if (judge[a] == nums[i] && i != judge1[a])
            {
                cout << i << ' ' << judge1[a];
                t = 1;
                break;
            }
            a ++;
            a %= N;
        }
        if (t) break;
    }
    return 0;
}

这是自己用vs写的,,,跟上面的差不多,,,代码写的比较烂,,哈哈,,还望各位读者能自己多多完善,,,

四,运行结果以及最后的一点点解释,,

在这里插入图片描述
一点点解释,,,我四舍五入一下等于没解释,,不过分吧,,哈哈,,(这第四点其实实在水字数) 咳咳,,,

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。