求两数之和(C++,哈希表)

问题:

  • 给定一个整数数组 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) 的算法吗?

来源:力扣(LeetCode)

初级受挫:

最初的思路是,target中的元素应该是少于nums的,所以先从target下手,寻找nums中小于target某一元素的子集,然后在子集中再继续计算结果。

寻找子集的过程想到的是for循环遍历target然后for循环遍历nums,子集的元素加入到unorderedset中。

在子集中寻找符合条件的元素组合暂时没有好的思路,应该是动态优化问题吧,遍历太麻烦了,我想到的是不断遍历累加,如果得到的值已经大于了target_element就没必要再继续算了,重新开始组合。但是如何重新组合呢?比如target元素为7,现在是1+3,再+5越界,这时应该是越过5找其他合适的。目前我想到的方法是通过一个键值对保存原来数组的索引的取值(应该是用unorderedmap实现吧),然后对进入子集的键值对再按照value排序(如何实现呢???),排序后只需要子集的首部开始累加就可以了,如果等于target_element就返回两个键值对的索引(如何实现呢???),如果大于target_element则跳出本次累加过程对下一个target_element进行累加。

#include<unordered_set>
#include<algorithm>
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    int numsSize(nums.size());
    int sum2(0);
    unordered_set<int> s;
        for (int x: target){
            for (int i=0; i<numsSize; i++){
                if (nums[i]<target && s.find(nums[i]) != s.end())
                    s.insert(nums[i]);
            }
            sort(s.begin(),s.end());
            for (int y : s){
                sum2+=y;
                if (sum2 == r)
            }

        }
    }
};

成功尝试:

上述思考失败后,不肯轻易放弃的我又想了一个简单的思路:
根据两数的限定条件,查找target_element - nums[i],并成功通过,总结经验如下:

  • 看清楚需求,输入的类型什么,返回类型是什么,然后再对症下药
  • 对输入数据的情况进行分析,常有0,负数,负正,正正,相同这几种情况,都不要疏漏。
  • return 的result直接用{j,k}表示!
#include<unordered_set>
#include<algorithm>
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    int numsSize(nums.size());
    int sum2(0);
    vector<int> result(2);
        for (int j=0; j<numsSize-1; j++){
            //if (nums[j]<=target){//考虑到0的情况应该是<=而非=
                sum2 = target - nums[j];
                for (int k=j+1; k<numsSize; k++){
                    //if (nums[k]<=target){//含有负数时不再适用,如[-3,3],0
                        if (nums[k]== sum2){
                            result[0]=j;
                            result[1]=k;
                            return result;
                        }

                    //}
                } 
            //}
        }
    return result;
    }
};

哈希表的优化解法:

综合上述的两个思考:

  • 认为unodered_map应该是基础
  • 核心思想为查找target_element - nums[i]
    解:
#include<unordered_map>
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    unordered_map<int,int> map;
        for(int i=0;i<nums.size();++i){
            /*if (map.find(target-nums[i]) != map.end())
                return {i,} 无指针无法返回值!!!
            */
            unordered_map<int,int>::iterator it = map.find(target-nums[i]);
            //auto it = map.find(target-nums[i]);
            if (it != map.end())
                return {it->second,i};//value
            map[nums[i]]=i;//key-value
        }
        return {};
    }
    
};

忘记分号,for循环忘记声明i的类型这种小问题不应该犯!!!
此外,注意unordered_map的使用:

  • find() 用于找key,然后配合iterator来指向first 或 second
  • 可以考虑auto指针 unordered_map<int,int>::iterator it = map.find(target-nums[i]); //auto it = map.find(target-nums[i]);
  • 注意for循环中一个常用的逻辑,和我们的常规思维不太一样的是,这里是一直if判断是否在(与本次循环有关的值),不在的话就加入本次循环的值,开启下一次循环。这样的时间复杂度就变成了O(n)!

再优化:

#include<unordered_map>
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int length = nums.size();
        unordered_map<int, int> numMap;
        for (int index = 0; index < length; index++) {
            if ( numMap.find(target - nums[index]) != numMap.end() ) {
                return {numMap[target - nums[index]], index};
            }
            numMap[nums[index]]=index;
        }
        return {};
    }
};
你可以使用哈希表来解决两数之和的问题。哈希表是一种将键和值进行映射的数据结构,它可以快速地查找给定键对应的值。以下是一个使用哈希表两数之和的示例代码: ```c #include <stdio.h> #include <stdbool.h> typedef struct { int key; int value; } HashNode; typedef struct { HashNode** table; int size; } HashMap; HashMap* createHashMap(int size) { HashMap* hashMap = (HashMap*)malloc(sizeof(HashMap)); hashMap->size = size; hashMap->table = (HashNode**)malloc(sizeof(HashNode*) * size); for (int i = 0; i < size; i++) { hashMap->table[i] = NULL; } return hashMap; } void put(HashMap* hashMap, int key, int value) { int hash = abs(key) % hashMap->size; while (hashMap->table[hash] != NULL && hashMap->table[hash]->key != key) { hash = (hash + 1) % hashMap->size; } if (hashMap->table[hash] != NULL) { free(hashMap->table[hash]); } HashNode* node = (HashNode*)malloc(sizeof(HashNode)); node->key = key; node->value = value; hashMap->table[hash] = node; } int get(HashMap* hashMap, int key) { int hash = abs(key) % hashMap->size; while (hashMap->table[hash] != NULL && hashMap->table[hash]->key != key) { hash = (hash + 1) % hashMap->size; } if (hashMap->table[hash] == NULL) { return -1; } else { return hashMap->table[hash]->value; } } bool containsKey(HashMap* hashMap, int key) { int hash = abs(key) % hashMap->size; while (hashMap->table[hash] != NULL && hashMap->table[hash]->key != key) { hash = (hash + 1) % hashMap->size; } return hashMap->table[hash] != NULL; } void freeHashMap(HashMap* hashMap) { for (int i = 0; i < hashMap->size; i++) { if (hashMap->table[i] != NULL) { free(hashMap->table[i]); } } free(hashMap->table); free(hashMap); } int* twoSum(int* nums, int numsSize, int target, int* returnSize) { HashMap* hashMap = createHashMap(numsSize); for (int i = 0; i < numsSize; i++) { int complement = target - nums[i]; if (containsKey(hashMap, complement)) { int* result = (int*)malloc(sizeof(int) * 2); result[0] = get(hashMap, complement); result[1] = i; *returnSize = 2; freeHashMap(hashMap); return result; } put(hashMap, nums[i], i); } freeHashMap(hashMap); return NULL; } int main() { int nums[] = {2, 7, 11, 15}; int target = 9; int returnSize; int* result = twoSum(nums, sizeof(nums) / sizeof(nums[0]), target, &returnSize); if (result != NULL) { printf("Indices: %d, %d\n", result[0], result[1]); free(result); } else { printf("No solution found.\n"); } return 0; } ``` 这段代码的思路是使用哈希表来存储每个元素的值和索引,然后遍历数组中的每个元素,查找是否存在与当前元素值相加等于目标值的另一个元素。如果存在,则返回这两个元素的索引。否则,返回NULL表示没有找到解决方案。 希望这可以帮助到你!如有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值