剑指 Offer 57. 和为s的两个数字

剑指 Offer 57. 和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

image-20210823181243121

image-20210823181252316

限制:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^6

思路一:二分查找,遍历数组元素,遍历时得到target与每个元素的差值,再用二分查找在数组里从当前元素开始向后找差值。

假设某个数组元素为nums[i],差值founder = target - num[i],左边界为nums[i],向后查找founder。因为nums[i]之前的元素都已经被遍历过了,founder如果存在,不可能在nums[i]之前。

在二分查找函数里用一个布尔变量flag来判断是否找到了founder,找到了返回founder,否则返回-1(数组元素大于等于1)

时间复杂度:O(N*logN)

代码:

int BinarySearch(int*nums, int begin, int numsSize, int target, bool flag)
{
    int mid = begin + (end - begin) / 2;
    while (begin <= end)
    {
        mid = begin + (end - begin) / 2;
        if (nums[mid] > target)
        {
            end = mid - 1;
        }
        else if (nums[mid] < target)
        {
            begin = mid + 1;
        }
        else
        {
            flag = true;
            break;
        }
    }

    if (flag == true)
    {
        return nums[mid];
    }
    else
    {
        return -1;
    }
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    if (numsSize == 0)
    {
        *returnSize = 0;
        return NULL;
    }
    
    int result = 0;
    int i = 0;
    while (i < numsSize)
    {
        printf("%d ", i);
        int founder = target - nums[i];

        //如果target与当前数组元素的值小于该数组元素,说明找不到这样的两个元素
        if (founder < nums[i])
        {
            *returnSize = 0;
            return NULL;
        }
        else
        {
            result = BinarySearch(nums, i, numsSize, founder, false);

            if (result == -1)//没找到,继续查找
            {
                i++;
                continue;
            }
            else//找到了
            {
                break;
            }
        }
    }

    //循环结束还没有找到
    if (result == -1)
    {
        *returnSize = 0;
        return NULL;
    }

    *returnSize = 2;
    int*ret = (int*)malloc(sizeof(int) * (*returnSize));
    ret[0] = nums[i];
    ret[1] = result;

    return ret;

}

自认为这个时间复杂度已经够快了,直到看到题解里的双指针、哈希表(只会用C的菜鸡还不懂哈希表)…

**思路二:**双指针遍历,一个指针指向数组左边界,一个指向右边界,类似二分思想

  • 当左指针元素与右指针元素之和大于target时,右指针向左走一步
  • 当两者之和小于target时,左指针向右走一步

代码:

int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    if (numsSize == 0)
    {
        *returnSize = 0;
        return NULL;
    }

    int left = 0;
    int right = numsSize - 1;
    *returnSize = 2;
    int*ret = (int*)malloc(sizeof(int) * (*returnSize));
    while (left <= right)
    {   
        if (nums[left] + nums[right] > target)//和偏大
        right--;
        else if (nums[left] + nums[right] < target)//和偏小
        left++;
        else//找到了
        {
            ret[0] = nums[left];
            ret[1] = nums[right];
            return ret;
        }
    }

    //出循环了说明没有找到
    *returnSize = 0;
    return NULL;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WoLannnnn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值