1. 两数之和(双指针 or 二分查找+自定义排序)

390 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

每日刷题第67天 2021.03.18

1. 两数之和

题目描述

  • 给定一个整数数组 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
  • 只会存在一个有效答案

思路分析

  • 两数之和,最开始的操作

思路的转变

  • 可以使用二分查找or双指针
  • 双指针的时间复杂度:o(n);二分查找的时间复杂度O(nlogn)
  • 求数组两数之和问题,想到使用左右指针,前提是有序的数组。但是由于题目要求返回的是原数组的索引,因此需要额外申请一个数组副本。
    • 1.申请数组副本,并进行升序排序,可直接使用快速排序库函数。
    • 2.对副本数组,使用左右指针,初始值左指针为0,右指针为数组末尾。
    • 3.比较两数之和与target,如果小于target,那左指针往前移动;如果大于target,那么右指针往后移动。
    • 4.如果相等,那么需要根据副本数组中的两个值,寻找在原数组中的索引,这里要特别注意,这两个值可能是相等的,需要找到不同的两个索引值。

map

  • 解题过程:
  • 首先:用map来存放{数组元素值,坐标}这样的键值对
  • 然后运用逆向解法,即用target减去数组中的某个元素,然后来判断map中是否有相同的值,若有则存在满足条件的答案,返回两个坐标即可;若没有,则保存{数组中某个元素值,对应的坐标}到map对象中。依次遍历即可判断是否有满足条件的两个元素。

AC代码

var twoSum = function(nums, target) {
  // 转变思路,选择nums[i] + nums[j] == target 就等价于 target - nums[i] = nums[j]
  // 那么就只需要在有序数组中查找符合要求的nums[j]即可
  // 二分查找
  // 时间复杂度o(nlogn)
  const len = nums.length;
  let ans = [];
  let index = [];
  for(let i = 0; i < len ; i++) {
    index[i] = i;
  }
  // 自定义排序
  index.sort((a, b) => {
    return nums[a] - nums[b];
  });
  nums.sort((a, b) => {
    return a - b;
  });
  // console.log(index);
  function binarySearch(cur){
    // console.log('cur',cur)
    let l = -1,r = len;
    while(l + 1 != r) {
      // console.log('l:', l,'r:', r)
      let mid = parseInt((l + r) / 2);
      // console.log('mid',mid,nums[mid])
      if(nums[mid] <= cur){
        l = mid;
      }else {
        r = mid;
      }
    }
    return l;
  }
  for(let i = 0; i < len; i++) {
    let tempt = target - nums[i];
    // console.log(tempt,'num:',nums[i])
    const targetIndex = binarySearch(tempt);
    // console.log(targetIndex)
    if(targetIndex != -1 && nums[targetIndex] == tempt){
      return [index[i], index[targetIndex]];
    }
  }
};

总结

  • 双指针的做法非常精妙,不要畏惧双指针,其就是相当于数组中的两个下标