当前位置: 首页 > news >正文

力扣每日打卡 1534. 统计好三元组 (简单)

力扣 1534. 统计好三元组 简单

  • 前言
  • 一、题目内容
  • 二、解题方法
    • 1. 暴力解法
    • 2.官方题解
      • 2.1 方法一:枚举
      • 2.2 方法二:枚举优化


前言

这是刷算法题的第十二天,用到的语言是JS
题目:力扣 1534. 统计好三元组 (简单)


一、题目内容

给你一个整数数组 arr ,以及 a、b 、c 三个整数。请你统计其中好三元组的数量。

如果三元组 ( a r r [ i ] , a r r [ j ] , a r r [ k ] ) (arr[i], arr[j], arr[k]) (arr[i],arr[j],arr[k]) 满足下列全部条件,则认为它是一个 好三元组 。

  • 0 < = i < j < k < a r r . l e n g t h 0 <= i < j < k < arr.length 0<=i<j<k<arr.length
  • ∣ a r r [ i ] − a r r [ j ] ∣ < = a |arr[i] - arr[j]| <= a arr[i]arr[j]<=a
  • ∣ a r r [ j ] − a r r [ k ] ∣ < = b |arr[j] - arr[k]| <= b arr[j]arr[k]<=b
  • ∣ a r r [ i ] − a r r [ k ] ∣ < = c |arr[i] - arr[k]| <= c arr[i]arr[k]<=c
    其中 ∣ x ∣ |x| x 表示 x x x 的绝对值。

返回 好三元组的数量

示例 1:
输入:arr = [3,0,1,1,9,7], a = 7, b = 2, c = 3
输出:4
解释:一共有 4 个好三元组:[(3,0,1), (3,0,1), (3,1,1), (0,1,1)] 。

示例 2:
输入:arr = [1,1,2,2,3], a = 0, b = 0, c = 1
输出:0
解释:不存在满足所有条件的三元组。

提示:

  • 3 < = a r r . l e n g t h < = 100 3 <= arr.length <= 100 3<=arr.length<=100
  • 0 < = a r r [ i ] < = 1000 0 <= arr[i] <= 1000 0<=arr[i]<=1000
  • 0 < = a , b , c < = 1000 0 <= a, b, c <= 1000 0<=a,b,c<=1000

二、解题方法

1. 暴力解法

三重for循环

代码如下(实例):

/*** @param {number[]} arr* @param {number} a* @param {number} b* @param {number} c* @return {number}*/
var countGoodTriplets = function (arr, a, b, c) {// 暴力算法let count = 0for (let i = 0; i < arr.length; i++) for (let j = i + 1; j < arr.length; j++) for (let k = j + 1; k < arr.length; k++) if (Math.abs(arr[i] - arr[j]) <= a && Math.abs(arr[j] - arr[k]) <= b && Math.abs(arr[i] - arr[k]) <= c) count++return count
}

2.官方题解

2.1 方法一:枚举

思路与算法

O ( n 3 ) O(n^3) O(n3) 的循环依次枚举所有的 ( i , j , k ) (i,j,k) (i,j,k),这里 0 ≤ i < j < k < a r r . l e n g t h 0≤i<j<k<arr.length 0i<j<k<arr.length,对于每组 ( i , j , k ) (i,j,k) (i,j,k),判断 a r r [ i ] 、 a r r [ j ] 、 a r r [ k ] arr[i]、arr[j]、arr[k] arr[i]arr[j]arr[k] 是否满足条件。

最终统计出所有满足条件的三元组的数量。

代码如下(示例):

var countGoodTriplets = function(arr, a, b, c) {const n = arr.length;let cnt = 0;for (let i = 0; i < n; ++i) {for (let j = i + 1; j < n; ++j) {for (let k = j + 1; k < n; ++k) {if (Math.abs(arr[i] - arr[j]) <= a && Math.abs(arr[j] - arr[k]) <= b && Math.abs(arr[i] - arr[k]) <= c) {++cnt;}}}}return cnt;
};作者:力扣官方题解
链接:https://leetcode.cn/problems/count-good-triplets/solutions/371340/tong-ji-hao-san-yuan-zu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
复杂度分析:
时间复杂度: O ( n 3 ) O(n^3) O(n3),其中 n n n 是数组 a r r arr arr 的长度。
空间复杂度: O ( 1 ) O(1) O(1)

链接:力扣本题官方题解
来源:力扣(LeetCode)

2.2 方法二:枚举优化

思路与算法
我们考虑 O ( n 2 ) O(n^2) O(n2) 枚举满足 ∣ a r r [ j ] − a r r [ k ] ∣ ≤ b ∣arr[j]−arr[k]∣≤b arr[j]arr[k]∣≤b 的二元组 ( j , k ) (j,k) (j,k),统计这个二元组下有多少 i i i 满足条件。由题目已知 i i i 的限制条件为 ∣ a r r [ i ] − a r r [ j ] ∣ ≤ a ∣arr[i]−arr[j]∣≤a arr[i]arr[j]∣≤a && ∣ a r r [ i ] − a r r [ k ] ∣ ≤ c ∣arr[i]−arr[k]∣≤c arr[i]arr[k]∣≤c,我们可以拆开绝对值,得到符合条件的值一定是 [ a r r [ j ] − a , a r r [ j ] + a ] [arr[j]−a,arr[j]+a] [arr[j]a,arr[j]+a] [ a r r [ k ] − c , a r r [ k ] + c ] [arr[k]−c,arr[k]+c] [arr[k]c,arr[k]+c] 两个区间的交集,我们记为 [ l , r ] [l,r] [l,r]。因此,在枚举 ( j , k ) (j,k) (j,k) 这个二元组的时候,我们只需要快速统计出满足 i < j i<j i<j a r r [ i ] arr[i] arr[i] 的值域范围在 [ l , r ] [l,r] [l,r] i i i 的个数即可。

很容易想到维护一个 a r r [ i ] arr[i] arr[i] 频次数组的前缀和 s u m sum sum,对于一个二元组 ( j , k ) (j,k) (j,k),我们可以 O ( 1 ) O(1) O(1) 得到答案为 s u m [ r ] − s u m [ l − 1 ] sum[r]−sum[l−1] sum[r]sum[l1]。考虑怎么维护保证当前频次数组存的数的下标符合 i < j i<j i<j 的限制,我们只要从小到大枚举 j j j,每次 j j j 移动指针加一的时候,将 a r r [ j ] arr[j] arr[j] 的值更新到 s u m sum sum 数组中即可,这样能保证枚举到 j j j 的时候 s u m sum sum 数组里存的值的下标满足限制。

「将 a r r [ j ] arr[j] arr[j] 的值更新到 s u m sum sum 数组中」这个操作在本方法中是暴力更新,因为数组的值域上限很小,有能力的读者可以考虑怎么在进一步优化这一部分的复杂度,可以从离散化或者树状数组的角度考虑,这里不再赘述。

代码如下(示例):

var countGoodTriplets = function(arr, a, b, c) {const n = arr.length, sum = new Array(1001).fill(0);let ans = 0;for (let j = 0; j < n; ++j) {for (let k = j + 1; k < n; ++k) {if (Math.abs(arr[j] - arr[k]) <= b) {const lj = arr[j] - a, rj = arr[j] + a;const lk = arr[k] - c, rk = arr[k] + c;const l = Math.max(0, Math.max(lj, lk)), r = Math.min(1000, Math.min(rj, rk));if (l <= r) {if (l === 0) {ans += sum[r];}else {ans += sum[r] - sum[l - 1];}}}}for (let k = arr[j]; k <= 1000; ++k) {sum[k] += 1;}}return ans;
};作者:力扣官方题解
链接:https://leetcode.cn/problems/count-good-triplets/solutions/371340/tong-ji-hao-san-yuan-zu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
复杂度分析:
时间复杂度: O ( n 2 + n S ) O(n^2+nS) O(n2+nS),其中 n n n 是数组 a r r arr arr 的长度, S S S 为数组的值域上限,这里为 1000 1000 1000
空间复杂度: O ( S ) O(S) O(S)。我们需要 O ( S ) O(S) O(S) 的空间维护 a r r [ i ] arr[i] arr[i] 频次数组的前缀和。

链接:力扣本题官方题解
来源:力扣(LeetCode)

相关文章:

  • 从代码学习深度学习 - 自注意力和位置编码 PyTorch 版
  • 记录 | Pycharm中如何调用Anaconda的虚拟环境
  • 基于MCP协议的多模态思维链在医疗系统改造中的融合研究
  • 【Code】《代码整洁之道》笔记-Chapter16-重构SerialDate
  • 驱动开发硬核特训 · USB 摄像头专题:原理 + 实战深度解析(基于 linux-imx)
  • Python爬虫第14节-如何爬取Ajax的数据
  • 代码随想录笔记-哈希表
  • 万字长篇————C语言指针学习汇总
  • 数据库表设计五层分类系统表设计
  • 测试定时发布
  • How AI could empower any business - Andrew Ng
  • VueDOMPurifyHTML 防止 ​​XSS(跨站脚本攻击)​​ 风险
  • 组合数哭唧唧
  • C# 基类型和派生类型之间的转型
  • DDS信号发生器设计(Quartus)
  • 35. 搜索插入位置
  • python数据类型处理题,输出素数题
  • Flink SQL SavePoint最佳实践
  • 【项目(一)】-仿mudou库one thread oneloop式并发服务器实现
  • 【Qt】界面优化
  • 苏州一季度GDP为6095.68亿元,同比增长6%
  • 日月谭天丨赖清德强推“脱中入北”是把台湾带向死路
  • 报告显示2024年全球军费开支增幅达冷战后最大
  • 解放日报头版头条:“五个中心”蹄疾步稳谱新篇
  • 当智驾成标配,车企暗战升级|2025上海车展
  • 伊朗阿巴斯港港口爆炸已致47人受伤