Bootstrap

有人相爱,有人夜里看海,有人力扣第一道题做不出来

有人相爱,有人夜里开车看海,有人leetcode第一题都做不出来。

—网友的话

题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

在这里插入图片描述

只会存在一个有效答案

进阶: 你可以想出一个时间复杂度小于 O(n2) 的算法吗?

思路

哈希表

双指针-碰撞指针

解题方法

哈希表

思路简述

遍历数组,判断匹配数是否存在哈希表中,存在就获取匹配数的返回值和索引,不存在就把这个数的数值和索引存入哈希表。然后继续循环判断。

步骤描述

  1. 创建哈希表
  2. 遍历数组,判断匹配数是否在哈希表中
  3. 匹配数在哈希表中,返回匹配数的数值和索引
  4. 匹配数不在哈希表中,将数组当前数值和索引存入哈希表

code

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
//使用哈希表解决两数之和
var twoSum = function(nums, target) {
//创建哈希表来保存数组中的值
const hash=new Map();
//迭代nums并将nums[i],index放入哈希表
    for(let i=0;i<nums.length;i++){
   // 判断另一个数是否存在哈希表中
     if(hash.has(target-nums[i])){
      //存在就获取两个数的下标
        return[hash.get(target-nums[i]),i]  ;    
     }
        //不存在,当前数值作为key,索引作为value存入哈希表
     hash.set( nums[i],i);
    }
};

复杂度分析

时间复杂度:

哈希表方法的时间复杂度, O ( n ) O(n) O(n)
n为数组nums的长度

空间复杂度:

哈希表方法的空间复杂度, O ( n ) O(n) O(n)

双指针-碰撞指针

思路简述

在有数组中定义左右指针,遍历时根据条件不同移动指针,进而从数组两端遍历数组。当两个指针对应数值的两数之和等于目标值的时候返回左右指针对应数值在原始数组中的数组下标。

步骤描述

碰撞指针就是在有序数组中定义left(数组的起始位置和right(数组的终止位置),
计算left和right的数值之和,
当两数之和等于目标值返回两个指针对应数值在原始数组中的数组下标,
若两数之和大于目标值,有指针左移,缩小两数之和的值,使其更接近目标值;
反之,若两数之和小于目标值,左指针右移,使得两数之和变大更接近目标值。

code


/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
//  使用双指针的碰撞指针解决本题
var twoSum = function (nums, target) {
    // 首先进行排序,保留原数组
    const sortedNums = Array.from(nums).sort((a, b) => a - b);
    // 定义双指针指向数组起始位置和结束位置
    let left = 0;
    let right = sortedNums.length - 1;

    while (true) {
        //计算左右指针对应数值之和
        const l = sortedNums[left];
        const r = sortedNums[right];
        const currentSum = l + r;
        // 如果左右指针对应数值之和等于目标值,返回左右指针对应数值在原始数组的位置的下标
        if (currentSum === target) {
            return [nums.indexOf(l), nums.lastIndexOf(r)];
            //如果当前左右指针对应数值之和大于目标值,有指针左移,减小和,使得两数之和更接近目标值
        } else if (currentSum > target) {
            right--;
        } else {
            left++;
        }
    }
};

注意事项

  1. 碰撞指针需要对数组进行排序,排序时注意不要污染原数组,所以代码中拷贝了nums,才使用Array.sort对拷贝数组进行排序。
  2. 返回结果需要考虑数组含有相同项。对于nums=[1,2,2,3],target=4这种case,其期望的返回值是[1,2]而不是[1,1]或者[2,2]。所以这里我们使用了Array.lastIndexOf()这个API。

复杂度分析

时间复杂度:

碰撞指针时间复杂度, O ( n ) O(n) O(n)

首先要对数组进行排序,双指针的复杂度是 O ( n ) O(n) O(n),所以碰撞指针算法的时间复杂度取决于排序的复杂度。

空间复杂度:

碰撞指针的空间复杂度, O ( n ) O(n) O(n)

只是拷贝了原数组,使用了一个数组长度的空间

;