第148场双周赛:循环数组中相邻元素的最大差值、将数组变相同的最小代价、最长特殊路径、所有安放棋子方案的曼哈顿距离

news2025/1/21 0:01:59

Q1、循环数组中相邻元素的最大差值

1、题目描述

给你一个 循环 数组 nums ,请你找出相邻元素之间的 最大 绝对差值。

**注意:**一个循环数组中,第一个元素和最后一个元素是相邻的。

2、解题思路

这个问题的核心是遍历循环数组并计算相邻元素之间的绝对差值。
由于数组是循环的,我们需要特别注意 第一个元素和最后一个元素 之间的差值。

步骤

  1. 遍历数组中所有相邻元素对,计算它们之间的绝对差值。
  2. 需要考虑 第一个元素和最后一个元素 之间的差值,因为这是一个循环数组。
  3. 返回所有差值中的最大值。

3、代码实现

class Solution {
public:
    int maxAdjacentDistance(vector<int>& nums) {
        int n = nums.size(); // 获取数组的大小
        int diff = 0;        // 初始化最大差值为 0

        // 遍历数组中每一对相邻元素
        for (int i = 1; i < n; ++i) {
            // 计算当前相邻元素对的绝对差值, 并更新最大差值
            diff = max(diff, abs(nums[i] - nums[i - 1]));
        }

        // 计算第一个元素和最后一个元素之间的绝对差值
        diff = max(diff, abs(nums[0] - nums[n - 1]));

        return diff; // 返回最大绝对差值
    }
};

在这里插入图片描述

4、复杂度分析

时间复杂度O(n),其中 n 是数组的大小。我们需要遍历数组一次来计算相邻元素的差值。

空间复杂度O(1),只使用了常量的额外空间。


Q2、将数组变相同的最小代价

1、题目描述

给你两个长度都为 n 的整数数组 arrbrr 以及一个整数 k 。你可以对 arr 执行以下操作任意次:

  • arr 分割成若干个 连续的 子数组,并将这些子数组按任意顺序重新排列。这个操作的代价为 k
  • 选择 arr 中的任意一个元素,将它增加或者减少一个正整数 x 。这个操作的代价为 x

请你返回将 arr 变为 brr最小 总代价。

子数组 是一个数组中一段连续 非空 的元素序列。

2、解题思路

思路分析

根据题目的描述,我们有两种可以影响总代价的操作:

  1. 调整元素:即对于 arr[i]brr[i],我们可以将 arr[i] 修改为 brr[i],其代价为 |arr[i] - brr[i]|
  2. 子数组操作:我们可以将 arr 按任意方式分割成连续的子数组,并将它们按任意顺序重新排列。这种操作的代价是 k

目标是选择最佳的策略,使得总代价最小。

关键思路

  • 直接修改:不进行子数组操作,直接通过调整元素将 arr 变为 brr,即每个元素都单独调整,代价为每个元素的差值的绝对值之和。
  • 排序后再调整:我们可以尝试通过分割并重新排列 arrbrr 来降低代价。如果排序后 arrbrr 的元素完全相同,那么我们可以将其分割并重新排列,使得代价仅为 k。然后再计算调整的代价。

最小代价即为这两种策略的较小值:直接调整代价或分割并重新排列后的代价。

3、代码实现

class Solution {
public:
    long long minCost(vector<int>& arr, vector<int>& brr, long long k) {
        // 第一种情况: 直接调整每个元素的值, 代价为每个元素的差值绝对值之和
        long long ret1 = 0;
        for (int i = 0; i < arr.size(); ++i) {
            ret1 += abs(arr[i] - brr[i]);
        }

        // 第二种情况: 将 arr 和 brr 排序, 并尝试通过最小代价的操作来调整
        ranges::sort(arr);  // 排序 arr
        ranges::sort(brr);  // 排序 brr
        long long ret2 = k; // 重新排列的代价是 k
        for (int i = 0; i < arr.size(); ++i) {
            ret2 += abs(arr[i] - brr[i]);
        }

        // 返回两种情况的最小值
        return min(ret1, ret2);
    }
};

在这里插入图片描述

4、复杂度分析

时间复杂度O(n log n),主要是排序的时间复杂度。

空间复杂度O(1),没有使用额外的空间。


Q3、最长特殊路径

1、题目描述

给你一棵根节点为节点 0 的无向树,树中有 n 个节点,编号为 0n - 1 ,这棵树通过一个长度为 n - 1 的二维数组 edges 表示,其中 edges[i] = [ui, vi, lengthi] 表示节点 uivi 之间有一条长度为 lengthi 的边。同时给你一个整数数组 nums ,其中 nums[i] 表示节点 i 的值。

特殊路径 指的是树中一条从祖先节点 往下 到后代节点且经过节点的值 互不相同 的路径。

注意 ,一条路径可以开始和结束于同一节点。

请你返回一个长度为 2 的数组 result ,其中 result[0]最长 特殊路径的 长度result[1] 是所有 最长特殊路径中的 最少 节点数目。

2、解题思路

  1. 树的表示与遍历

    • 题目给定的是一棵无向树,树的每条边有一个权重,即边的长度。我们可以利用邻接表来表示这棵树,其中每个节点有一个列表,表示与其相连的节点及边的长度。
  2. 特殊路径的定义

    • 一条特殊路径要求路径中节点的值互不相同。换句话说,路径上不能出现重复的节点值。

    • 我们需要找到从根节点 0 到所有后代节点的路径中,满足该条件的最长路径。

  3. 深度优先搜索 (DFS)

    • 我们可以使用 DFS 来遍历树,并通过路径的长度和路径上的节点值来判断是否符合特殊路径的条件。

    • 在 DFS 过程中,我们需要记录当前路径上的节点值,通过一个 unordered_map 来标记每个节点值最后出现的深度位置,从而避免路径中出现重复的节点值。

    • 我们需要在每次递归时保持对路径长度的更新,并且通过比较路径的长度来更新结果。

  4. 结果计算

    • 维护一个变量 result 来记录当前的最大路径长度和最小节点数。

    • 在递归时,对于每一条路径,我们会计算其长度,并检查是否是最大路径。如果是,我们还需要更新最小节点数。

3、代码实现

class Solution {
public:
    vector<int> longestSpecialPath(vector<vector<int>>& edges, vector<int>& nums) {
        int n = nums.size();

        // 构建图的邻接表表示
        vector<vector<pair<int, int>>> graph(n);
        for (const auto& edge : edges) {
            int u = edge[0], v = edge[1], w = edge[2];
            graph[u].emplace_back(v, w); // u -> v
            graph[v].emplace_back(u, w); // v -> u
        }

        // 初始化答案为最小值
        pair<int, int> result = {-1, 0};      // result.first: 最大路径长度, result.second: 最小节点数
        vector<int> pathLength = {0};         // 路径的累计长度
        unordered_map<int, int>lastSeenDepth; // 记录每个节点值的最后一次出现的深度

        // 深度优先搜索 (DFS) 函数, 计算特殊路径
        auto dfs = [&](auto&& dfs, int node, int parent, int lastSeen) -> void {
            int currentValue = nums[node]; // 当前节点的值
            int previousDepth = lastSeenDepth[currentValue]; // 当前值上次出现的深度

            // 更新当前路径中最大的深度
            lastSeen = max(lastSeen, previousDepth);

            // 更新答案, 计算当前路径长度和节点数
            result = max(result, make_pair(pathLength.back() - pathLength[lastSeen], lastSeen - (int)pathLength.size()));

            // 更新当前节点值的最后出现位置
            lastSeenDepth[currentValue] = pathLength.size();

            // 遍历所有邻接节点 (子节点)
            for (const auto& [nextNode, edgeWeight] : graph[node]) {
                // 避免访问父节点
                if (nextNode != parent) {
                    pathLength.push_back(pathLength.back() + edgeWeight);   // 更新路径长度
                    dfs(dfs, nextNode, node, lastSeen);                     // 递归访问子节点
                    pathLength.pop_back();                                  // 回溯, 恢复路径长度
                }
            }

            // 恢复当前节点值的上次出现深度
            lastSeenDepth[currentValue] = previousDepth;
        };

        // 从根节点 0 开始深度优先搜索 (DFS)
        dfs(dfs, 0, -1, 0);

        // 返回最长路径长度和最少节点数
        return {result.first, -result.second};
    }
};

在这里插入图片描述

4、复杂度分析

时间复杂度O(n)。树的每个节点和每条边都仅被访问一次,DFS 的复杂度为 O(n),其中 n 是节点数。

空间复杂度O(n)。使用邻接表 graph 存储树结构,pathLength 数组和 lastSeenDepth 哈希表分别需要 O(n) 的空间。


Q4、所有安放棋子方案的曼哈顿距离

1、题目描述

给你三个整数 mnk

给你一个大小为 m x n 的矩形格子,它包含 k 个没有差别的棋子。请你返回所有放置棋子的 合法方案 中,每对棋子之间的曼哈顿距离之和。

一个 合法方案 指的是将所有 k 个棋子都放在格子中且一个格子里 至多 只有一个棋子。

由于答案可能很大, 请你将它对 109 + 7 取余 后返回。

两个格子 (xi, yi)(xj, yj) 的曼哈顿距离定义为 |xi - xj| + |yi - yj|

2、解题思路

  1. 树的表示与遍历

    • 题目给定的是一棵无向树,树的每条边有一个权重,即边的长度。我们可以利用邻接表来表示这棵树,其中每个节点有一个列表,表示与其相连的节点及边的长度。
  2. 特殊路径的定义

    • 一条特殊路径要求路径中节点的值互不相同。换句话说,路径上不能出现重复的节点值。

    • 我们需要找到从根节点 0 到所有后代节点的路径中,满足该条件的最长路径。

  3. 深度优先搜索 (DFS)

    • 我们可以使用 DFS 来遍历树,并通过路径的长度和路径上的节点值来判断是否符合特殊路径的条件。

    • 在 DFS 过程中,我们需要记录当前路径上的节点值,通过一个 unordered_map 来标记每个节点值最后出现的深度位置,从而避免路径中出现重复的节点值。

    • 我们需要在每次递归时保持对路径长度的更新,并且通过比较路径的长度来更新结果。

  4. 结果计算

    • 维护一个变量 result 来记录当前的最大路径长度和最小节点数。

    • 在递归时,对于每一条路径,我们会计算其长度,并检查是否是最大路径。如果是,我们还需要更新最小节点数。

3、代码实现

const int MOD = 1'000'000'007;
const int MAX = 100'000;

// 定义阶乘和阶乘的逆元
long long fact[MAX];     // fact[i] 表示 i 的阶乘
long long inv_fact[MAX]; // inv_fact[i] 表示 i 的阶乘的逆元

// 快速幂函数, 计算 x 的 n 次方 % MOD
long long mod_pow(long long x, int n) {
    long long result = 1;
    while (n) {
        if (n % 2) {
            result = (result * x) % MOD;
        }
        x = (x * x) % MOD;
        n /= 2;
    }
    return result;
}

// 预计算阶乘和阶乘逆元
auto init = [] {
    fact[0] = 1;
    for (int i = 1; i < MAX; i++) {
        fact[i] = (fact[i - 1] * i) % MOD;
    }

    inv_fact[MAX - 1] = mod_pow(fact[MAX - 1], MOD - 2); // 使用费马小定理计算逆元
    for (int i = MAX - 2; i >= 0; i--) {
        inv_fact[i] = (inv_fact[i + 1] * (i + 1)) % MOD;
    }
    return 0;
}();

// 组合数公式计算 C(n, m) % MOD
long long comb(int n, int m) {
    if (m < 0 || m > n) {
        return 0;
    }
    return fact[n] * inv_fact[m] % MOD * inv_fact[n - m] % MOD;
}

// 计算曼哈顿距离的和
class Solution {
public:
    int distanceSum(int m, int n, int k) {
        // 计算所有的曼哈顿距离之和
        long long total_distance = calculateTotalDistance(m, n);

        // 计算选择k个位置的方式
        long long ways_to_choose_k_positions = comb(m * n - 2, k - 2);

        // 结果是两者的乘积, 取模
        return (total_distance * ways_to_choose_k_positions) % MOD;
    }

private:
    // 计算曼哈顿距离之和
    long long calculateTotalDistance(int m, int n) {
        long long row_distance = m * (1LL * n * n - 1) + n * (1LL * m * m - 1);
        long long total_distance = m * n * row_distance / 6;
        return total_distance % MOD;
    }
};

在这里插入图片描述

4、复杂度分析

时间复杂度O(n)。树的每个节点和每条边都仅被访问一次,DFS 的复杂度为 O(n),其中 n 是节点数。

空间复杂度O(n)。使用邻接表 graph 存储树结构,pathLength 数组和 lastSeenDepth 哈希表分别需要 O(n) 的空间。



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2279569.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑换固态硬盘

参考&#xff1a; https://baijiahao.baidu.com/s?id1724377623311611247 一、根据尺寸和缺口可以分为以下几种&#xff1a; 1、M.2 NVME协议的固态 大部分笔记本是22x42MM和22x80MM nvme固态。 在京东直接搜&#xff1a; M.2 2242 M.2 2280 2、msata接口固态 3、NGFF M.…

opengrok_windows_环境搭建

软件列表 软件名下载地址用途JDKhttps://download.java.net/openjdk/jdk16/ri/openjdk-1636_windows-x64_bin.zipindex 使用java工具tomcathttps://dlcdn.apache.org/tomcat/tomcat-9/v9.0.98/bin/apache-tomcat-9.0.98-windows-x64.zipweb服务器opengrokhttps://github.com/o…

《offer 来了:Java 面试核心知识点精讲 -- 原理篇》

在 Java 面试的战场上,只知皮毛可不行,面试官们越来越看重对原理的理解。今天就给大家分享一本能让你在面试中脱颖而出的 “武林秘籍”——《offer 来了:Java 面试核心知识点精讲 -- 原理篇》。 本书详细介绍了Java架构师在BAT和移动互联网公司面试中常被问及的核心知识,内…

Linux之网络套接字

Linux之网络套接字 一.IP地址和端口号二.TCP和UDP协议2.1网络字节序 三.socket编程的常见API四.模拟实现UDP服务器和客户端五.模拟实现TCP服务器和客户端 一.IP地址和端口号 在了解了网络相关的基础知识之后我们知道了数据在计算机中传输的流程并且发现IP地址在其中占据了确定…

迈向 “全能管家” 之路:机器人距离终极蜕变还需几步?

【图片来源于网络&#xff0c;侵删】 这是2024年初Figure公司展示的人形机器人Figure 01&#xff0c;他可以通过观看人类的示范视频&#xff0c;在10小时内经过训练学会煮咖啡&#xff0c;并且这个过程是完全自主没有人为干涉的&#xff01; 【图片来源于网络&#xff0c;侵删】…

几何数据结构之四叉树与八叉树

几何数据结构之四叉树与八叉树 四叉树的定义四叉树深度的计算公式推导假设&#xff1a;计算过程&#xff1a;1. 划分空间&#xff1a;2. 节点容纳的最小距离&#xff1a;3. 解出深度&#xff1a;4. 考虑常数项&#xff1a; 总结&#xff1a; 八叉树 四叉树的定义 四叉树&#…

(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)

一、四大坐标系介绍 1&#xff0c;世界坐标系 从这个世界&#xff08;world&#xff09;的视角来看物体 世界坐标系是3D空间坐标&#xff0c;每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw​,Yw​,Zw​)表示 2&#xff0c;相机坐标系 相机本身具有一个坐标系&…

嵌入式知识点总结 C/C++ 专题提升(一)-关键字

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.C语言宏中"#“和"##"的用法 1.1.(#)字符串化操作符 1.2.(##)符号连接操作符 2.关键字volatile有什么含意?并举出三个不同的例子? 2.1.并行设备的硬件寄存…

重塑商业智能:大数据改变商业的十种方式

在过去几年间&#xff0c;大数据一直在改变许多公司的运营方式。大数据指的是大量且多样的数据集&#xff0c;当这些数据被妥善收集和分析时&#xff0c;人们能够从中获取有价值的洞察信息。随着大数据逐渐应用于中小型企业&#xff0c;它有望彻底变革企业运营模式。以下将介绍…

基于Spring Boot的车间调度管理系统

基于 Spring Boot 的车间调度管理系统 一、系统概述 基于 Spring Boot 的车间调度管理系统是一个为制造企业车间生产活动提供智能化调度和管理解决方案的软件系统。它利用 Spring Boot 框架的便捷性和高效性&#xff0c;整合车间内的人员、设备、物料、任务等资源&#xff0c…

Ubuntu 24.04 LTS 安装 tailscale 并访问 SMB共享文件夹

Ubuntu 24.04 LTS 安装 tailscale 安装 Tailscale 官方仓库 首先&#xff0c;确保系统包列表是最新的&#xff1a; sudo apt update接下来&#xff0c;安装 Tailscale 所需的仓库和密钥&#xff1a; curl -fsSL https://tailscale.com/install.sh | sh这会自动下载并安装 …

Ubuntu 22.04 TLS 忘记root密码,重启修改的解决办法

1.想办法进入这个界面&#xff0c;我这里是BIOS引导的是按Esc按一下就行&#xff0c;UEFI的貌似是按Shift不得而知&#xff0c;没操作过。下移到Advanced options for Ubuntu&#xff0c;按enter 2.根据使用的内核版本&#xff0c;选择带「recovery mode」字样的内核版本&#…

故障诊断 | BWO白鲸算法优化KELM故障诊断(Matlab)

目录 效果一览文章概述BWO白鲸算法优化KELM故障诊断一、引言1.1、研究背景及意义1.2、故障诊断技术的现状1.3、研究目的与内容二、KELM基本理论2.1、KELM模型简介2.2、核函数的选择2.3、KELM在故障诊断中的应用三、BWO白鲸优化算法3.1、BWO算法基本原理3.2、BWO算法的特点3.3、…

TCP状态转移图详解

状态 描述 LISTEN represents waiting for a connection request from any remote TCP and port. SYN-SENT represents waiting for a matching connection request after having sent a connection request. SYN-RECEIVED represents waiting for a confirming connect…

LabVIEW 水电站厂内经济运行系统

基于 LabVIEW 的水电站经济运行系统&#xff0c;主要针对农村小水电站运行管理的不足进行改进&#xff0c;通过精确控制发电与用水量&#xff0c;最小化耗水量并优化负荷分配&#xff0c;提升水电站的运营效率和经济效益。 ​ LabVIEW 在系统中的功能特点 强大的图形化编程环…

蓝桥杯训练—矩形面积交

文章目录 一、题目二、示例三、解析四、代码 一、题目 平面上有两个矩形&#xff0c;它们的边平行于直角坐标系的X轴或Y轴&#xff0c;对于每个矩形&#xff0c;我们给出它的一对相对顶点的坐标&#xff0c;请你编程写出两个矩形的交的面积 输入格式&#xff1a; 输入包含两行…

Flask简介与安装以及实现一个糕点店的简单流程

目录 1. Flask简介 1.1 Flask的核心特点 1.2 Flask的基本结构 1.3 Flask的常见用法 1.3.1 创建Flask应用 1.3.2 路由和视图函数 1.3.3 动态URL参数 1.3.4 使用模板 1.4 Flask的优点 1.5 总结 2. Flask 环境创建 2.1 创建虚拟环境 2.2 激活虚拟环境 1.3 安装Flask…

基于机器学习的电信用户流失预测与数据分析可视化

完整源码项目包获取→点击文章末尾名片&#xff01; 背景描述 根据IBM商业社区分享团队描述&#xff0c;该数据集为某电信公司在加利福尼亚为7000余位用户&#xff08;个人/家庭&#xff09;提供电话和互联网服务的相关记录。描述用户基本情况&#xff0c;包括每位用户已注册的…

InVideo AI技术浅析(五):生成对抗网络

一、特效生成 1. 工作原理 特效生成是计算机视觉中的高级应用,旨在通过算法生成高质量的视觉特效,如风格迁移、图像到图像的翻译等。InVideo AI 使用生成对抗网络(GAN)来实现这一功能。GAN 通过生成器和判别器两个网络的对抗训练,生成逼真的视觉特效。 2. 关键技术模型…

Linux操作系统的灵魂,深度解析MMU内存管理

在计算机的奇妙世界里&#xff0c;我们每天使用的操作系统看似流畅自如地运行着各类程序&#xff0c;背后实则有着一位默默耕耘的 “幕后英雄”—— 内存管理单元&#xff08;MMU&#xff09;。它虽不常被大众所熟知&#xff0c;却掌控着计算机内存的关键命脉&#xff0c;是保障…