首页 > 其他分享 >LeetCode - 1 两数之和

LeetCode - 1 两数之和

时间:2024-08-28 16:57:55浏览次数:12  
标签:index target nums int buckets 数组 LeetCode 两数

题目来源

1. 两数之和 - 力扣(LeetCode)

题目描述

给定一个整数数组 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 <= 10^4
  • -10^9 <= nums[i] <= 10^9
  • -10^9 <= target <= 10^9
  • 只会存在一个有效答案

题目解析

本题我们只需要遍历一遍数组 nums 即可找出数组中 "和为 target" 的两个元素及其索引位置。

具体实现是:

  • 首先,定义一个字典dic(哈希表),用于记录已遍历过的数组元素和其索引位置,即字典的key为数组元素,value为数组元素的索引位置。
  • 然后,遍历数组 nums,假设此时被遍历出来的元素是 num,索引位置为 index,那么满足要求的另一个元素应该是 target - num,因此我们可以在字典 dic 中查找是否存在 target - num:
  1. 若存在,则找到了符合要求的两个数组元素,他们的位置分别是:index 和 dic[target - num]
  2. 若不存在,则我们应该记录此时 num 的索引位置 index,即 dic[num] = index

按照上面逻辑,遍历完所有数组元素,即可找到题解。

C源码实现

C语言没有内置的哈希表实现,因此下面我们自己手搓了一个简易的哈希表。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
typedef struct Node {
    int num;
    int index;
    struct Node *next;
} Node;

typedef struct Link {
    Node *head;
} Link;

typedef struct HashTable {
    Link **buckets;
    int buckets_size;
} HT;

Node *new_Node(int num, int index) {
    Node *node = (Node *) malloc(sizeof(Node));
    node->num = num;
    node->index = index;
    node->next = NULL;
    return node;
}

Link *new_Link() {
    Link *link = (Link *) malloc(sizeof(Link));
    link->head = NULL;
    return link;
}

HT *new_HashTable(int buckets_size) {
    HT *ht = (HT *) malloc(sizeof(HT));
    ht->buckets_size = buckets_size;
    ht->buckets = (Link **) calloc(buckets_size, sizeof(Link *));
    return ht;
}

int get_HashTable(HT *ht, int num) {
    int buckets_index = abs(num % ht->buckets_size);

    Link *link = ht->buckets[buckets_index];

    if (link != NULL) {
        Node *cur = link->head;
        while (cur != NULL) {
            if (cur->num == num) {
                return cur->index;
            }
            cur = cur->next;
        }
    }

    return -1;
}

void put_HashTable(HT *ht, int num, int index) {
    int buckets_index = abs(num % ht->buckets_size);

    if (ht->buckets[buckets_index] == NULL) {
        ht->buckets[buckets_index] = new_Link();
    }

    Node *cur = ht->buckets[buckets_index]->head;
    while (cur != NULL) {
        if (cur->num == num) {
            cur->index = index;
            return;
        }
        cur = cur->next;
    }

    Node *node = new_Node(num, index);

    if (ht->buckets[buckets_index]->head != NULL) {
        node->next = ht->buckets[buckets_index]->head;
    }

    ht->buckets[buckets_index]->head = node;
}

int *twoSum(int *nums, int numsSize, int target, int *returnSize) {
    int *result = (int *) malloc(sizeof(int) * 2);
    *returnSize = 2; // 记录返回值result数组有几个元素

    // 哈希表用于记录已遍历过的数组元素及其索引位置,key为数组元素,value为数组元素的索引位置
    HT *ht = new_HashTable(100000); // 初始化哈希表的容量

    for (int i = 0; i < numsSize; i++) { // 遍历数组元素
        int remain = target - nums[i];

        int index = get_HashTable(ht, remain); // 检查已遍历过的数组元素中是否有 target - nums[i]
        if (index != -1) { // 若有, 则找到了和为target的两个数组元素的索引位置
            result[0] = index;
            result[1] = i;
            return result;
        } else { // 若没有,则记录 nums[i] 和其索引位置 i
            put_HashTable(ht, nums[i], i);
        }
    }

    return result;
}

 

C++源码实现

unordered_map性能要比map好一点,find操作要比count操作性能更好一点

class Solution {
public:
    vector<int> twoSum(vector<int> &nums, int target) {
        unordered_map<int, int> dic; // 记录已遍历过的数组元素及其索引位置,key为数组元素,value为数组元素的索引位置

        for (int i = 0; i < nums.size(); i++) {
            int remain = target - nums[i];

            if (dic.find(remain) != dic.end()) { // 检查已遍历过的数组元素中是否有 target - nums[i]
                return vector < int > {dic[remain], i}; // 若有, 则找到了和为target的两个数组元素的索引位置
            } else {
                dic[nums[i]] = i; // 若没有,则记录 nums[i] 和其索引位置 i
            }
        }

        return {};
    }
};

 

Java源码实现

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();  // 记录已遍历过的数组元素及其索引位置,key为数组元素,value为数组元素的索引位置

        for (int i = 0; i < nums.length; i++) {
            int remain = target - nums[i];

            if (map.containsKey(remain)) { // 检查已遍历过的数组元素中是否有 target - nums[i]
                return new int[] { map.get(remain), i }; // 若有, 则找到了和为target的两个数组元素的索引位置
            } else {
                map.put(nums[i], i); // 若没有,则记录 nums[i] 和其索引位置 i
            }
        }

        return null;
    }
}

 

Python源码实现

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        dic = {}  # 记录已遍历过的数组元素及其索引位置,key为数组元素,value为数组元素的索引位置

        for i in range(len(nums)):
            remain = target - nums[i]

            if remain in dic:  # 检查已遍历过的数组元素中是否有 target - nums[i]
                return [dic[remain], i]  # 若有,则找到了和为target的两个数组元素的索引位置
            else:
                dic[nums[i]] = i  # 若没有,则记录 nums[i] 和其索引位置 i

        return []

 

JavaScript源码实现

虽然使用JS对象模拟哈希表性能更优一点,但是使用Map类语义化更好一点

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
  const map = new Map(); // 记录已遍历过的数组元素及其索引位置,key为数组元素,value为数组元素的索引位置

  for(let i=0; i<nums.length; i++) {
      const remain = target - nums[i];

      if(map.has(remain)) { // 检查已遍历过的数组元素中是否有 target - nums[i]
          return [map.get(remain), i]; // 若有, 则找到了和为target的两个数组元素的索引位置
      } else {
          map.set(nums[i], i); // 若没有,则记录 nums[i] 和其索引位置 i
      }
  }

  return [];
};

标签:index,target,nums,int,buckets,数组,LeetCode,两数
From: https://blog.csdn.net/2401_86994545/article/details/141642717

相关文章

  • 单调队列--滑动窗口最大值(leetcode23)
    目录一、单调队列介绍二、题目应用1.题目描述2.解题碎碎念3.代码示例三、扩展1.与优先队列区别2.单调队列其他题目一、单调队列介绍单调队列是一种特殊的队列数据结构,它能够在常数时间内找到队列中的最值。单调队列可以用来解决一些与最值相关的问题,例如滑动窗口最......
  • 56. 合并区间【 力扣(LeetCode) 】
    一、题目描述  以数组intervals表示若干个区间的集合,其中单个区间为intervals[i]=[starti,endi]。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。二、测试用例示例1:输入:intervals=[[1,3],[2,6],[8,10],[15,18]]输......
  • 【Hot100】LeetCode—39. 组合总和
    目录1-思路2-实现⭐39.组合总和——题解思路3-ACM实现题目连接:39.组合总和1-思路注意如果借助startIndex实现,理解startIndex的含义在本题目中,由于同一个元素可以重复选取,因此startIndex在传递的过程中,不需要进行+1操作,传递的值为i2-实现⭐39......
  • 【Hot100】LeetCode—17. 电话号码的字母组合
    目录1-思路String数组(哈希表)+回溯2-实现⭐17.电话号码的字母组合——题解思路3-ACM实现题目连接:17.电话号码的字母组合1-思路String数组(哈希表)+回溯思路通过String数组实现哈希表,存储0-9的哈希表映射回溯三部曲①参数及返回值numToStr:Stri......
  • 【Leetcode_Hot100】普通数组
    普通数组53.最大子数组和56.合并区间189.轮转数组238.除自身以外数组的乘积41.缺失的第一个正数53.最大子数组和方法一:暴力解依次遍历数组中的每个子数组,进而判断res的最大值超时classSolution{publicintmaxSubArray(int[]nums){intres=0;......
  • 135. 分发糖果(leetcode)
    https://leetcode.cn/problems/candy/description/贪心,策略是确定一侧的正确性,再确定另一侧的正确性,最后综合作为正确答案,其中先确定一侧的正确性是局部最优,确定两侧的正确性的局部最优,且找不到反例就可以推出全局最优答案classSolution{publicintcandy(int[]ra......
  • 程序员必备的的5个刷题网站。大厂面试稳了 力扣 https://leetcode.cn
    程序员必备的的5个刷题网站。大厂面试稳了力扣https://leetcode.cn1、leetcode力扣。网址:https://leetcode.cnLeetCode是一个定位为求职的刷题网站,其中又以算法题为主。很多大厂在面试的时候,都会考算法。有空就刷一刷这里面的算法题,你的算法水平肯定会有大幅的提升,不管是求职,......
  • LeetCode 算法:爬楼梯 c++
    原题链接......
  • 搜索二维矩阵 II(LeetCode)
    题目编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:每行的元素从左到右升序排列。每列的元素从上到下升序排列。解题"""时间复杂度为O(m+n),其中m是矩阵的行数,n是矩阵的列数。"""defsearchMatrix(matrix,t......
  • 每日一题:Leetcode-47 全排列
    力扣题目解题思路java代码力扣题目:给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。示例1:输入:nums=[1,1,2]输出:[[1,1,2],[1,2,1],[2,1,1]]示例2:输入:nums=[1,2,3]输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]解......