1543.统计好三元组(简单)

题目

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

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

  • 0 <= i < j < k < arr.length
  • |arr[i] - arr[j]| <= a
  • |arr[j] - arr[k]| <= b
  • |arr[i] - arr[k]| <= c

其中 |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
解释:不存在满足所有条件的三元组。
bash 复制代码
#include <stdlib.h>
int countGoodTriplets(int* arr, int arrSize, int a, int b, int c) {
    int count = 0;
    for(int i = 0;i < arrSize;i++){
        for(int j = i + 1;j < arrSize;j++){
            for(int k = j+1;k < arrSize;k++){
                if(abs(arr[i] - arr[j]) <= a
                && abs(arr[j] - arr[k]) <= b
                && abs(arr[i] - arr[k]) <= c){
                     count++;
                }
            }
        }
    }
    return count;
}
python 复制代码
def countGoodTriplets(arr, a, b, c):
    # 初始化计数器,统计合格三元组数目
    count = 0
    # 获取数组长度,后续循环边界使用
    n = len(arr)
    
    # i:第一个元素下标
    for i in range(n):
        # j:第二个下标,必须在i之后
        for j in range(i + 1, n):
            # 剪枝,i‑j差值超标,直接跳过当前j,省去k循环
            if abs(arr[i] - arr[j]) > a:
                continue
            # k:第三个下标,必须在j之后,天然 i<j<k
            for k in range(j + 1, n):
                # 校验剩余两个绝对值条件
                if abs(arr[j] - arr[k]) <= b and abs(arr[i] - arr[k]) <= c:
                    count += 1
    # 返回结果
    return count


# 测试示例代码
if __name__ == "__main__":
    test_arr = [3,0,1,1,9,7]
    print(countGoodTriplets(test_arr,7,2,3))
cpp 复制代码
#include <vector>
#include <cmath>   // abs绝对值函数头文件
using namespace std;

class Solution {
public:
    int countGoodTriplets(vector<int>& arr, int a, int b, int c) {
        // count:用来记录符合条件好三元组的总数
        int count = 0;
        // i代表三元组第一个元素的下标
        for (int i = 0; i < arr.size(); i++)
        {
            // j必须大于i,第二个元素下标,保证 i < j
            for (int j = i + 1; j < arr.size(); j++)
            {
                // 剪枝:如果i,j已经不满足条件,直接跳过该j,不用遍历k循环,节省性能
                if (abs(arr[i] - arr[j]) > a)
                {
                    continue;
                }
                // k必须大于j,第三个元素下标,保证 i<j<k
                for (int k = j + 1; k < arr.size(); k++)
                {
                    // 判断剩下两条绝对值约束
                    if (abs(arr[j] - arr[k]) <= b && abs(arr[i] - arr[k]) <= c)
                    {
                        count ++; // 满足全部条件,计数器 +1
                    }
                }
            }
        }
        // 循环结束,返回最终合格三元组数量
        return count;
    }
};

i 从左往右固定第一个元素

j 固定在 i 之后,先检验 i,j 的差值,如果超过 a,直接跳过该 j,不用遍历 k(剪枝优化)

k 固定在 j 之后,检验 j‑k、i‑k 的绝对值条件

全部条件成立,计数器 + 1

语法问题:为什么python不用arrsize

C/C++ 需要手动传入数组长度

int countGoodTriplets(int* arr, int arrSize, int a, int b, int c)

  • C 的 int* arr 只是内存首地址指针
  • 指针本身不知道数组一共有多少个元素
  • 所以必须额外传参数 arrSize,告知数组长度,用来控制循环终止条件
  • 如果你没有长度,程序不知道循环什么时候停下,会访问越界内存

C++ vector

vector<int>& arr

vector 是封装好的容器,可以调用 **arr.size()**获取内部存储元素数量,不需要单独传长度参数。

Python 列表本身自带属性

def countGoodTriplets(arr, a, b, c):

n = len(arr)

  • Python 的 arr 是 list 对象(容器),不是 C 语言那种光秃秃的内存指针;
  • 对象内部已经保存好了元素总数;
  • 内置函数 len(列表) 随时可以读取列表长度;
  • 函数不需要单独接收数组大小参数,随时**len(arr)**即可拿到。
cpp 复制代码
vector<int>& arr

vector:C++ 标准库动态数组容器,相当于 Python 的 list、C 语言可变数组

<int>:容器里面存放的数据类型是 int‑整型

& = 引用

arr 是参数名字

整体含义:接收一个存放 int 的 vector 容器的引用

& 引用到底干什么

写法 1(不带引用:值传递)

cpp 复制代码
vector<int> arr

函数调用的时候,把原数组完整复制一份副本给到函数内 arr

arr 只是拷贝出来的复制品 ;函数内部修改 arr,外面原数组不受影响

数组很大时拷贝非常消耗内存、速度慢

写法 2(带 &,引用传递,也就是别名)

cpp 复制代码
vector<int>& arr

arr 只是外面原 vector 的别名、外号,它们指向同一块内存。

不会复制整个数组,只是绑定原对象

速度快,零拷贝

在函数内修改 arr,外面原本的数组也跟着改动

相关推荐
大明者省6 小时前
WSL2 Ubuntu22.04 GPU训练环境配置指南
人工智能·算法·计算机视觉
WWJA王文举7 小时前
I²C通信完整流程详解:START、地址、ACK、数据、Repeated START和STOP一次讲透
c语言·开发语言
zhanghaha13147 小时前
Python进阶教程:6_JSON 数据解析 —— 新手完全指南
开发语言·python·json
白狐_7988 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander2588 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
Shell运维手记8 小时前
Linux 常用基础命令学习笔记
linux·运维·笔记·学习·算法·github
qq_448011168 小时前
C语言中的动态内存分配
c语言·开发语言·php
杨航 AI8 小时前
O(n log n):线性对数原理拆解 这个是排序算法的黄金复杂度之一。
算法·排序算法
船厂电气自动化ai大模型9 小时前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
旖旎夜光9 小时前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口