【Leetcode 每日一题 - 补卡】1534. 统计好三元组

问题背景

给你一个整数数组 a r r arr arr,以及 a 、 b 、 c a、b 、c 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 \le i < j < k < arr.length 0≤i<j<k<arr.length
  • ∣ a r r [ i ] − a r r [ j ] ∣ ≤ a |arr[i] - arr[j]| \le a ∣arr[i]−arr[j]∣≤a
  • ∣ a r r [ j ] − a r r [ k ] ∣ ≤ b |arr[j] - arr[k]| \le b ∣arr[j]−arr[k]∣≤b
  • ∣ a r r [ i ] − a r r [ k ] ∣ ≤ c |arr[i] - arr[k]| \le c ∣arr[i]−arr[k]∣≤c

其中 ∣ x ∣ |x| ∣x∣ 表示 x x x 的绝对值。

返回 好三元组的数量

数据约束

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

解题过程

题中要求的约束有三个,暴力枚举的时间复杂度是 O ( N 3 ) O(N ^ 3) O(N3)。

如果数组是有序的,那可以很容易地提高时间方面的效率,但是结果与元素的初始位置有关,所以不方便直接排序。

退而求其次,定义一个下标数组,对它进行排序。

然后将数组中的元素当作 j j j 来遍历,将满足 ∣ a r r [ i ] − a r r [ j ] ∣ ≤ a |arr[i] - arr[j]| \le a ∣arr[i]−arr[j]∣≤a 以及 ∣ a r r [ j ] − a r r [ k ] ∣ ≤ b |arr[j] - arr[k]| \le b ∣arr[j]−arr[k]∣≤b

两个条件的原数组中的元素分别记录到哈希表中。

接下来只要再求满足第三个条件的元素对的数量,根据绝对值的定义,可以在线性的时间内得到合法结果的上下限。

具体实现

java 复制代码
class Solution {
    public int countGoodTriplets(int[] arr, int a, int b, int c) {
        Integer[] idx = new Integer[arr.length];
        Arrays.setAll(idx, i -> i);
        Arrays.sort(idx, (i, j) -> arr[i] - arr[j]);

        int res = 0;
        for (int j : idx) {
            int cur = arr[j];
            List<Integer> list1 = new ArrayList<>();
            for (int i : idx) {
                if (i < j && Math.abs(arr[i] - cur) <= a) {
                    list1.add(arr[i]);
                }
            }

            List<Integer> list2 = new ArrayList<>();
            for (int k : idx) {
                if (k > j && Math.abs(arr[k] - cur) <= b) {
                    list2.add(arr[k]);
                }
            }

            int left = 0;
            int right = 0;
            for (int item : list1) {
                while (right < list2.size() && list2.get(right) <= item + c) {
                    right++;
                }
                while (left < list2.size() && list2.get(left) < item - c) {
                    left++;
                }
                res += right - left;
            }
        }
        return res;
    }
}
相关推荐
前端小白在前进12 分钟前
⭐力扣刷题:螺旋矩阵
算法·leetcode·矩阵
老赵聊算法、大模型备案5 小时前
北京市生成式人工智能服务已备案信息公告(2025年12月11日)
人工智能·算法·安全·aigc
CoderYanger6 小时前
C.滑动窗口-求子数组个数-越长越合法——2799. 统计完全子数组的数目
java·c语言·开发语言·数据结构·算法·leetcode·职场和发展
厕所博士6 小时前
红黑树原理前置理解—— 2-3 树
算法·2-3树·红黑树原理理解前置
萌>__<新7 小时前
力扣打卡每日一题————除自身外所有元素的乘积
数据结构·算法
xu_yule7 小时前
算法基础—搜索(2)【记忆化搜索+BFS+01BFS+Floodfill]
数据结构·算法
s09071367 小时前
Xilinx FPGA使用 FIR IP 核做匹配滤波时如何减少DSP使用量
算法·fpga开发·xilinx·ip core·fir滤波
老马啸西风8 小时前
成熟企业级技术平台-10-跳板机 / 堡垒机(Bastion Host)详解
人工智能·深度学习·算法·职场和发展
子夜江寒8 小时前
逻辑回归简介
算法·机器学习·逻辑回归
软件算法开发8 小时前
基于ACO蚁群优化算法的多车辆含时间窗VRPTW问题求解matlab仿真
算法·matlab·aco·vrptw·蚁群优化·多车辆·时间窗