【刷力扣 TS 版】难度 中等 三数&四数之和

简介: 【刷力扣 TS 版】难度 中等 三数&四数之和

原文来自 我的个人博客

前言

拒绝摆烂ヾ(◍°∇°◍)ノ゙

从今天开始(2023/02/12),定一个小目标,先刷个 300Leetcode 题目(之前刷的不计入)。

当然作为一个小前端,我选择的语言是 TS,而且刷的题目的难度会偏中等一些,大概按照 简单3 中等6 困难1 这样的题型分布吧。嗯,目前是这么打算的。

本题 Github 地址:因为比较喜欢 vscode 的界面,而且方便调试,所以 AC 完就顺便提到 github 了,也算做一个记录吧。

本篇的题目是这个系列的第

  1. NO.2615. 三数之和
  2. NO.2716. 最接近的三数之和
  3. NO.2818. 四数之和

1. 三数之和

1.1 题目描述

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意: 答案中不可以包含重复的三元组。

示例 1:

输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入: nums = [0,1,1]
输出: []
解释: 唯一可能的三元组和不为 0 。

示例 3:

输入: nums = [0,0,0]
输出: [[0,0,0]]
解释: 唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

1.2 解:排序 + 双指针

这道题的难点在于如何去除重复解

我们的思路是这样的

  1. 首先将数组从小到大排序
  2. 然后遍历数组
  3. 在一层遍历的的内部定义两个指针,一个start指针指向剩下部分的头,另一个end指针指向剩余部分的尾部
  4. 接着判断三个数相加,如果小于 0start 指针 +1,如果大于 0end 指针 -1,如果等于 0startend 指针不等于上一个值时说明当前三个数肯定不重合即得到我们需要的组合
function threeSum(nums: number[]): number[][] {
  nums = nums.sort((prev, next) => prev - next);
  const ret: number[][] = [];
  const n = nums.length;

  for (let i = 0; i < n; i++) {
    let start = i + 1;
    let end = nums.length - 1;
    let prevStartNum, prevEndNum;
    if (nums[i] === nums[i - 1]) continue;
    while (start < end) {
      const sum = nums[i] + nums[start] + nums[end];
      if (sum < 0) {
        prevStartNum = nums[start];
        start++;
      }
      if (sum > 0) {
        prevEndNum = nums[end];
        end--;
      }

      if (sum === 0) {
        if (prevEndNum !== nums[end] && prevStartNum !== nums[start]) {
          ret.push([nums[i], nums[start], nums[end]]);
        }
        prevStartNum = nums[start];
        prevEndNum = nums[end];
        start++;
        end--;
      }
    }
  }
  return ret;
}

复杂度分析:

  • 时间复杂度:这里的时间复杂度比较复杂,数组排序 O(nlogn),遍历数组 O(n),双指针 O(n),最终的时间复杂度为 O(n2)
  • 空间复杂度:O(1)

2. 最接近的三数之和

2.1 题目描述

给你一个长度为 n 的整数数组 nums 和一个目标值 target。请你从 nums中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例 1:

输入: nums = [-1,2,1,-4], target = 1
输出: 2
解释: 与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

示例 2:

输入: nums = [0,0,0], target = 1
输出: 0

提示:

  • 3 <= nums.length <= 1000
  • -1000 <= nums[i] <= 1000
  • -104 <= target <= 104

2.2 解:排序+双指针

这道题和上一道很相似,只不过上题的目标是找相等的,这题的目标是找最接近的。

我们依然可以使用上面的排序+双指针,这次定义一个无限大的值 ret,当找到 三数和与 target 的差比 ret 小的时候 就改变 ret,直到遍历完数组找到相加三数和与 target相等

function threeSumClosest(nums: number[], target: number): number {
  const length = nums.length;
  let ret = Infinity;
  nums.sort((prev, next) => prev - next);
  for (let i = 0; i < length; i++) {
    let start = i + 1,
      end = length - 1;
    while (start < end) {
      const sum = nums[i] + nums[start] + nums[end];
      ret = Math.abs(target - sum) < Math.abs(target - ret) ? sum : ret;
      if (sum < target) start++;
      else if (sum > target) end--;
      else return sum;
    }
  }
  return ret;
}

复杂度与上一题相似就不分析了。

3. 四数之和

3.1 题目描述

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

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

示例 1:

输入: nums = [1,0,-1,0,-2,2], target = 0
输出: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

输入: nums = [2,2,2,2,2], target = 8
输出: [[2,2,2,2]]

提示:

  • 1 <= nums.length <= 200
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109

3.2 解

相关文章
|
12月前
【力扣-TS解题】1、回文数
【力扣-TS解题】1、回文数
42 0
|
存储 前端开发 JavaScript
【刷力扣 TS 版】难度 简单 队列&栈专题
【刷力扣 TS 版】难度 简单 队列&栈专题
【刷力扣 TS 版】难度 简单 队列&栈专题
|
存储 算法 前端开发
【刷力扣 TS 版】难度 中等 链表专题(四)
【刷力扣 TS 版】难度 中等 链表专题(四)
【刷力扣 TS 版】难度 中等 链表专题(四)
|
存储 前端开发
【刷力扣 TS 版】难度 中等 链表专题(三)
【刷力扣 TS 版】难度 中等 链表专题(三)
【刷力扣 TS 版】难度 中等 链表专题(三)
|
算法 前端开发 Go
【刷力扣 TS 版】难度 简单 链表专题(二)
【刷力扣 TS 版】难度 简单 链表专题(二)
【刷力扣 TS 版】难度 简单 链表专题(二)
|
前端开发 测试技术 Go
【刷力扣 TS 版】难度 简单 链表专题(一)
【刷力扣 TS 版】难度 简单 链表专题(一)
【刷力扣 TS 版】难度 简单 链表专题(一)
|
算法 前端开发 Go
【刷力扣 TS 版】难度 简单,二叉树的前序遍历&后序遍历
【刷力扣 TS 版】难度 简单,二叉树的前序遍历&后序遍历
【刷力扣 TS 版】难度 简单,二叉树的前序遍历&后序遍历
|
前端开发 Go 对象存储
【刷力扣 TS 版】难度 简单,x 的平方根 & 验证回文串
【刷力扣 TS 版】难度 简单,x 的平方根 & 验证回文串
【刷力扣 TS 版】难度 简单,x 的平方根 & 验证回文串
|
前端开发 Go
【刷力扣 TS 版】难度 简单,二进制求和
【刷力扣 TS 版】难度 简单,二进制求和
【刷力扣 TS 版】难度 简单,二进制求和
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
41 6