LeetCode 1. 两数之和---双指针索引和哈希表

双指针索引思路

排序:首先,对输入的数组 nums 进行排序。排序后,可以利用双指针技术来查找两个数的和是否等于目标值 target。
双指针查找:使用两个指针 i 和 j 分别指向排序后数组的两端,i 从左端开始,j 从右端开始。比较两个指针指向的元素之和与目标值 target 的关系:如果和等于 target,则找到了这两个数,跳出循环。如果和大于 target,则移动右指针 j 向左移动,减小和的值。如果和小于 target,则移动左指针 i 向右移动,增加和的值。
记录索引:在找到两个数的和等于目标值后,需要找到这两个数在原始数组 clone 中的索引。由于排序后数组的元素顺序发生了变化,所以不能直接使用 i 和 j 作为索引。因此,使用一个布尔数组 Keys 来记录 clone 数组中每个元素是否已经被访问过,以及两个布尔标志 flags 来标记是否已经找到对应的索引。
返回结果:最后返回包含两个数索引的数组 res。

解题过程

检查输入数组 nums 的长度是否小于 2,如果是,则直接返回空数组 res。
创建一个 clone 数组作为 nums 的副本,用于在查找索引时保持原始顺序。
对 nums 数组进行排序。
初始化两个指针 i 和 j,以及一个用于存储结果的数组 res。
进入循环,比较两个指针指向的元素之和与目标值 target 的关系,并根据比较结果移动指针。
当找到两个数的和等于目标值时,跳出循环。
使用两个布尔数组 Keys 和 flags 来找到 clone 数组中对应于 nums 数组中找到的两个数的索引。
返回包含这两个索引的数组 res。

复杂度

时间复杂度: O(Nlogn) = 排序O(n log n) + 双指针O(n) + 索引O(n)
空间复杂度: O(N)

Code

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int n = nums.size();
        vector<int> res(2,0);
        if(n<2) return res;
        vector<int> clone = nums;
        sort(nums.begin(),nums.end());
        int i = 0,j=n-1,ans= 0;
        while(i<j){
            ans = nums[i]+nums[j];
            res[0] = nums[i];
            res[1] = nums[j];
            if(ans==target){
                break;
            }else if(ans>target){
                j--;
            }else{
                i++;
            }
        }
        vector<bool> Keys(n,false);
        vector<bool> flags(2,false);
        for(int i = 0;i<n;i++){
            if(!flags[0]&&res[0]==clone[i]&&!Keys[i]) {
                res[0] = i;
                Keys[i] = true;
                flags[0] = true;
            }
            if(!flags[1]&&res[1]==clone[i]&&!Keys[i]) {
                res[1] = i;
                Keys[i] = true;
                flags[1] = true;
            }
        }
        return res;
        
    }
};

哈希表思路

哈希表存储:使用一个哈希表 hash 来存储数组 nums 中的每个元素及其对应的索引。哈希表的键是数组中的元素值,值是该元素在数组中的索引。

查找配对:遍历数组 nums,对于每个元素 nums[i],计算 gap,即 target 减去当前元素的值。这个 gap 就是我们需要找到的另一个数,使得它与当前元素的和等于 target。

检查是否存在:在哈希表中查找 gap 是否已经存在。如果存在,说明我们已经找到了一对数,它们的和等于 target,并且可以直接返回这两个数的索引。

存储当前元素索引:如果 gap 不在哈希表中,将当前元素 nums[i] 及其索引 i 存入哈希表。

返回结果:如果遍历完整个数组都没有找到符合条件的配对,返回 {0,0} 作为默认结果

解题过程

定义一个 unordered_map 类型的变量 hash 来存储元素值和索引的对应关系。

使用一个 for 循环遍历数组 nums。

在循环内部,对于每个元素 nums[i],计算 gap,即 target - nums[i]。

使用 hash.find(gap) != hash.end() 检查 gap 是否已经在哈希表中。如果 gap 存在,说明找到了一对数,它们的和等于 target,返回这两个数的索引,即 {hash[gap], i}。

如果 gap 不在哈希表中,将当前元素 nums[i] 及其索引 i 存入哈希表 hash[nums[i]] = i。

如果遍历完整个数组都没有找到符合条件的配对,返回 {0,0}。

复杂度

时间复杂度: O(N)
空间复杂度: O(N)

Code

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> hash;
        for(int i=0;i<nums.size();i++){
            int gap = target-nums[i];
            if(hash.find(gap)!=hash.end())return {hash[gap],i};
            hash[nums[i]]=i;
        }
        return {0,0};
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值