leetcode高频题精选

两数之和

/*
  给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
  你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

  给定 nums = [2, 7, 11, 15], target = 9
  因为 nums[0] + nums[1] = 2 + 7 = 9
  所以返回 [0, 1]
*/
export function twoNumberAdd(nums: number[], target: number) {
  // 思路:我们可以在遍历数组的过程中,增加一个Map结构来存储已经遍历过的数字及其对应的索引值。然后每遍历到一个新数字的时候,都回到Map里去查询targetNum与该数的
  // 差值是否已经在前面出现过,若出现过则答案已经显现,我们就不在往下走了。
  let diffs = {}
  for (let i = 0; i < nums.length; i++) {
    // 判断当前值与target的差值是否存在
    if (diffs[target - nums[i]] !== undefined) {
      return [diffs[target - nums[i]], i]
    }
    // 若没有对应差值,则记录当前值
    diffs[nums[i]] = i
  }
}

三数之和

/*
  三数之和
  给你一个包含那个整数的数组nums,判断nums中是否存在三个元素a,b,c使得a+b+c=0,请你找出所有满足条件且重复的三元组。
  注意:答案中不可以包含重复的三元组。
  示例:
    给定数组nums = [-1, 0, 1, 2, -1, -4],
    满足条件的三元组集合为
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]


    思路:
      跟两数之和一样,我们把求和的问题变成求差的问题:固定其中一个数,在剩下的数中寻找是否有两个数的和
    和这个固定的数相加和是0
      这里才用  双指针法  来解决问题,相比三层循环,效率会大大提升。
*/
/*
    双指针法的适用范围比较广,一般像求和,比大小都可用它来解决,但是有一个前提:数组必须有序。
*/
/*
    因此我们的第一步是给数组进行排序,升序排列
    nuns = nums.sort((a, b) => {
      return a - b
    })
    然后对数组进行遍历,每遍历到哪个数字,就固定当前数字。同时左指针指向该数字后面的紧邻的那个数字,
    右指针指向数组末尾。然后左右指针分别向中间靠拢
    每次指针移动一次位置,就计算一下两个指针指向数字之和加上固定的那个数之后,是否等于0。如果是,
    那我们就得到了一个目标组合;否则,分两种情况来看:
    1.相加之和大于0,说明右侧的数偏大,右指针左移
    2.相加之和小于 0,说明左侧的数偏小了,左指针右移
*/

threeSum(nums: number[]) {
    // 用于存放结果的数组
    let res: any = []
    // 给nums排序
    nums = nums.sort((a, b) => {
      return a - b
    })
    // 缓存数组的长度
    const len = nums.length
    for (let i = 0; i < len - 2; i++) {
      // 左指针j
      let j = i + 1
      // 右指针k
      let k = len - 1
      // 如果遇到重复的数字 则跳过
      if (i > 0 && nums[i] === nums[i - 1]) {
        continue
      }
      while (j < k) {
        // 三数之和小于0,左指针前进
        if (nums[i] + nums[j] + nums[k] < 0) {
          j++
          // 处理左指针元素重复的情况
          while (j < k && nums[j] === nums[j - 1]) {
            j++
          }
        } else if (nums[i] + nums[j] + nums[k] > 0) {
          // 三数之和大于0,右指针后退
          k--

          // 处理右指针元素重复的情况
          while (j < k && nums[k] === nums[k + 1]) {
            k--
          }
        } else {
          res.push([nums[i], nums[j], nums[k]])
          // 左右指针一起前进
          j++
          k--
          // 若左指针元素重复,跳过
          while (j < k && nums[j] === nums[j - 1]) {
            j++
          }

          // 若右指针元素重复,跳过
          while (j < k && nums[k] === nums[k + 1]) {
            k--
          }
        }
      }
    }
    // 返回结果数组
    return res
  }

盛最多水的容器

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
在这里插入图片描述

  maxArea(heightArr) {
    let max = 0
    let i = 0
    let j = heightArr.length - 1
    while (i < j) {
      let minHeight = Math.min(heightArr[i], heightArr[j])
      let area = (j - i) * minHeight
      max = Math.max(max, area)
      // 如果左侧小于右侧,则i++,否则j--(这一步其实就是取所有高度中比较高的,我们知道面积等于长*宽)
      if (heightArr[i] < heightArr[j]) {
        i++
      } else {
        j--
      }
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值