LeetCode 第464场周赛 第三天

1. 3658 奇数和与偶数和的最大公约数(欧几里得)

链接:题目链接
题解

题解时间复杂度O(logmin(a, b))

  1. 获得前n个奇、偶数的总和,由于数列为等差数列,等差数列和公式:(a1 + an) * n / 2),可以快速求和。
  2. 获取两个数字的最大公约数,用欧几里得算法可求得最大公约数,代码模版如下。

代码

    class Solution {public int gcd(int a, int b) {return b != 0 ? gcd(b, a % b) : a;}public int gcdOfOddEvenSums(int n) {// 等差数列求和int sum1 = (1 + 2 * n - 1) * n / 2;int sum2 = (2 + 2 * n) * n / 2;return gcd(sum1, sum2);}
}

2. 3659 数组元素分组(抽屉原理)

链接:题目链接
题解

题解时间复杂度O(n):

  1. nums 中的每个元素必须被分配到恰好一个组中,每个组恰好k个不同的元素,说明 n * k = 数组长度,n为具体组数。
  2. 组数 = 数组长度 / k,如果某个数字重复次数 > 组数,那么肯定没办法满足每个组恰好k个不同的元素(抽屉原理),反之均可满足。

代码

class Solution {public boolean partitionArray(int[] nums, int k) {int len = nums.length;if (len % k != 0) {return false;}int countLimit = len / k;Map<Integer, Integer> numCountMap = new HashMap<>();for (int num: nums) {numCountMap.put(num, numCountMap.getOrDefault(num, 0) + 1);}return numCountMap.values().stream().noneMatch(numCount -> numCount > countLimit);}
}

3. 3660 跳跃游戏 9(预处理 单调栈 二分解法)

链接:题目链接
题解

背景:仅当 nums[j] < nums[i] 时,才允许跳跃到下标 j,其中 j > i。 仅当 nums[j] > nums[i] 时,才允许跳跃到下标 j,其中 j < i。(一次跳跃中,往前跳,nums值必须严格大于; 往后跳,nums值必须严格小于);
题解时间复杂度O(nlogn)

  1. 对于第i个元素,如果能到达的最大值在左侧,那么一次跳跃即可(需要维护左侧最大值)。
  2. 对于第i个元素,如果能到达的最大值在右侧,首先往右跳跃到j位置,nums[j] < nums[i]的,所以nums[j]肯定不是i元素能到达的最大值,意味着还得从j下标往左跳,才有可能 num[j] > nums[i]。
  3. 注意:对于第i个元素,最大值在右侧还有一种跳跃方式。可能存在[30, 10, 35, 22] 这种情况,对于nums[1]来说,并不能直接跳到35去(因为nums[2、3] > nums[1]),但是有一条路线可以达到nums[3](1 -> 0 -> 3 -> 2),(第2、3点)总结:对于最大值在右侧情况,nums[i]可以先跳到左侧最大值(nums[j] >= nums[i]),再往右侧跳(覆盖的范围更广)
  4. 因为要在logn级别找到 i右边元素到达的最大值,那么很自然想到了维护一个有序的列表,通过二分方式在logn时间复杂度找到右侧能到达的最大值。这里维护有序列表有个关键点:如果 2能到达x,3能达到x-1或者x,那么这个列表还有必要维护3这个元素吗?答案是不需要将3这个元素入队(因为能到达2的元素包含了能到达3的元素 且 3能到达的最大值<=2能到达的最大值),也就是单调栈思想
  5. 有序列表样例:[1 -> 10, 2 -> 12, 5 -> 15],此时有序是指的nums[i]是递增的,且nums[i]能找到的最大值也是递增的。所以在二分查找的时候只需要找到小于nums[i]的第一个元素,再拿到它对应的最大值即可。
  6. 第i个元素能到达的最大值 = max(左侧最大值, 右侧最大值)

代码

 class Solution {public int[] maxValue(int[] nums) {int len = nums.length;int[] leftMaxValues = new int[len];int maxValue = 0;for (int i = 0; i < len; ++ i) {maxValue = Math.max(maxValue, nums[i]);leftMaxValues[i] = maxValue;}int[] result = new int[len];TreeMap<Integer, Integer> map = new TreeMap<>();// 初始化result[len - 1] = leftMaxValues[len - 1];map.put(nums[len - 1], leftMaxValues[len - 1]);for (int i = len - 2; i >= 0; -- i) {// 获取右边最大值Map.Entry<Integer, Integer> entry = map.lowerEntry(leftMaxValues[i]);if (entry != null) {result[i] = entry.getValue();} else {result[i] = leftMaxValues[i];}// 维护mapInteger old = map.get(nums[i]);if (old == null || old < result[i]) {map.put(nums[i], result[i]);// 删除所有 "比nums[i]大,且 value <= result[0]" 的节点while (true) {Map.Entry<Integer, Integer> higher = map.higherEntry(nums[i]);if (higher != null && higher.getValue() <= result[i]) {map.remove(higher.getKey());} else break;}}}return result;}}

4. 3661 可以被机器人摧毁的最大墙壁数目(DP解法)

链接:题目链接
题解

题解 时间复杂度O(nlogn)

  1. 因为机器人会阻挡子弹的穿透,所以第i个机器人,最多穿透[i - 1, i + 1]下标的区域,那么也以为着第i个机器人只与第i-1、i+1个机器人有关系
  2. robot、distance 为一组信息 walls为一组信息,两组信息分别排序(机器人跟相邻机器人有关系 所以需要排序处理)
  3. 这里机器人只能往左往右发射,可以用f[i][j] i表示第i个机器人 j表示往左还是右设计 j为0 往左 j为1往右
  4. dp转移方程式: f[i][1] = Math.max(f[i - 1][0], f[i - 1][1]) + i机器人往右打多少个墙; f[i][0] = Math.max(f[i - 1][0], f[i - 1][1]) + i机器人往左打多少个墙
  5. 打多少个墙?可以拿到机器人射击区间,因为墙列表也做了排序(是有序的),再通过二分计算能射击多少个墙
  6. 注意1:这里要注意i-1机器人往右,i机器人往左射击的情况,对射的情况(避免重复计算墙
  7. 注意2:这里要考虑机器人与墙重合的情况,比如i机器人与墙重合,但是i-1机器人往右射击 计算了该墙,但是i机器人射击又计算该墙的情况(又重复计算了),所以墙与机器人重合情况,该墙只让该机器人射击。(i-1机器人往右射击,区间从[nums[i-1], nums[i]] -> [nums[i-1], nums[i] -1))

代码

class Solution {class Pair implements Comparable<Pair>{private int robotIndex;private int distance;@Overridepublic int compareTo(Pair pair) {return robotIndex - pair.robotIndex;}public Pair(int robotIndex, int distance) {this.robotIndex = robotIndex;this.distance = distance;}}public int maxWalls(int[] robots, int[] distance, int[] walls) {int len = robots.length;List<Pair> pairs = new ArrayList<>(len);for (int i = 0; i < len; ++ i) {pairs.add(new Pair(robots[i], distance[i]));}Collections.sort(pairs);Arrays.sort(walls);int[][] f = new int[len + 1][2];for (int i = 1; i <= len; ++ i) {if (i == 1) {f[i][1] = caclSum(0, pairs, pairs.get(0).distance, walls, false, true);f[i][0] = caclSum(0, pairs, pairs.get(0).distance, walls, true, true);} else {f[i][1] = Math.max(f[i - 1][0], f[i - 1][1]) + caclSum(i - 1, pairs, pairs.get(i - 1).distance, walls, false, true);Pair pair = pairs.get(i - 1);Pair prePair = pairs.get(i - 2);if (pair.distance + prePair.distance >= pair.robotIndex - prePair.robotIndex) {f[i][0] = Math.max(f[i - 1][0] + caclSum(i - 1, pairs, pair.distance, walls, true, true), Math.max(f[i][0], Math.max(f[i - 2][0], f[i - 2][1]) + caclSum(i - 2, pairs, pair.distance + prePair.distance, walls, false, false)));} else {f[i][0] = Math.max(f[i - 1][1], f[i - 1][0]) + caclSum(i - 1, pairs, pair.distance, walls, true, true);}}}return Math.max(f[len][0], f[len][1]);}public int caclSum(int index, List<Pair> pairs, int distance, int[] walls, boolean left, boolean excludeNextIndex) {int l, r;if (left) {r = pairs.get(index).robotIndex;l = r - distance;if (index - 1 >= 0) {l = Math.max(l, pairs.get(index - 1).robotIndex + (excludeNextIndex ? 1 : 0));}} else {l = pairs.get(index).robotIndex;r = l + distance;if (index + 1 < pairs.size()) {r = Math.min(r, pairs.get(index + 1).robotIndex - (excludeNextIndex ? 1 : 0));}}int wallLIndex, wallRIndex;// 找到大于等于l的第一个下标int wallL = 0, wallR = walls.length - 1;while (wallL < wallR) {int mid = (wallL + wallR) >> 1;if (walls[mid] >= l) {wallR = mid;} else {wallL = mid + 1;}}wallLIndex = wallL;// 找到小于等于R的第一个下标wallL = 0;wallR = walls.length - 1;while (wallL < wallR) {int mid = (wallL + wallR + 1) >> 1;if (walls[mid] <= r) {wallL = mid;} else {wallR = mid - 1;}}wallRIndex = wallL;if (wallLIndex <= wallRIndex && walls[wallLIndex] >= l && walls[wallRIndex] <= r) {return wallRIndex - wallLIndex + 1;}return 0;}
}

如果对你有帮助,辛苦点个赞,谢谢啦,朋友!!!

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

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

相关文章

IntelliJ IDEA 集成 ApiFox 操作与注解规范指南

一、IDEA装入Apifox 1.安装Apifox Helper 说明:在 IntelliJ IDEA 中安装 ApiFox Helper 插件。 2.打开Apifox 说明:点击 设置,在菜单中选择 API访问令牌。在弹出的窗口中输入任意名称,并选择令牌的有效期(为了方便,我这里选择了 无期限)。生成令牌后,由于 令牌只能复…

C++---双指针

在C编程中&#xff0c;双指针算法是一种高效的解题思路&#xff0c;其核心是通过设置两个指针&#xff08;或索引&#xff09;遍历数据结构&#xff08;如数组、链表、字符串等&#xff09;&#xff0c;利用指针的移动规则减少无效操作&#xff0c;从而将时间复杂度从暴力解法的…

【LLM】GLM-4.5模型架构和原理

note 文章目录note一、GLM-4.5模型二、Slime RL强化学习训练架构Reference一、GLM-4.5模型 大模型进展&#xff0c;GLM-4.5技术报告,https://arxiv.org/pdf/2508.06471&#xff0c;https://github.com/zai-org/GLM-4.5&#xff0c;包括GLM-4.5&#xff08;355B总参数&#xff…

LLM 中增量解码与模型推理解读

在【LLM】LLM 中 token 简介与 bert 实操解读一文中对 LLM 基础定义进行了介绍&#xff0c;本文会对 LLM 中增量解码与模型推理进行解读。 一、LLM 中增量解码定义 增量解码&#xff08;Incremental Decoding&#xff09;是指在自回归文本生成过程中&#xff0c;模型每次只计…

1.Spring Boot:超越配置地狱,重塑Java开发体验

目录 一、Spring框架&#xff1a;伟大的基石 历史背景与挑战 Spring的革命性贡献 新的挑战&#xff1a;配置地狱 二、Spring Boot&#xff1a;约定大于配置的革命 四大核心特性 1. 快速创建独立应用 2. 自动配置&#xff1a;智能化的魔法 3. 起步依赖&#xff1a;依赖管…

assert使用方法

assert 是 Python 中用来进行 调试 和 验证 的一个关键字&#xff0c;它用于测试一个 条件表达式 是否为真。如果条件为假&#xff0c;assert 会抛出一个 AssertionError 异常&#xff0c;通常带有错误信息。语法&#xff1a;assert condition, "Error message"condi…

【实习总结】快速上手Git:关键命令整理

目录 git的四大工作区域 git首次配置 克隆远程仓库 提交代码到远程仓库 查看文件状态&#xff08;可选&#xff09; 添加文件到暂存区 将暂存区的内容提交到本地仓库 将本地的提交上传到远程仓库 拉取并合并代码 第一种方式 第二种方式 分支管理 查看与创建分支 …

02-开发环境搭建与工具链

第2课&#xff1a;开发环境搭建与工具链 &#x1f4da; 课程目标 掌握DevEco Studio的下载、安装和配置熟悉HMS Core&#xff08;华为移动服务&#xff09;的使用了解鸿蒙模拟器与真机调试环境掌握必备开发工具的使用 &#x1f6e0;️ DevEco Studio环境搭建 2.1 下载与安装…

删掉一个元素以后全为1的最长子数组-滑动窗口

1493. 删掉一个元素以后全为 1 的最长子数组 - 力扣&#xff08;LeetCode&#xff09; Solution #include<iostream> #include<vector> using namespace std;class Solution { public://滑动窗口//动态维护一个窗口&#xff0c;窗口内只能有1个0&#xff0c;记录窗…

【计算机网络 | 第8篇】编码与调制

文章目录通信系统中的编码与调制&#xff1a;从信道基础到信号传输技术一、信道与通信电路&#x1f342;二、三种基本通信方式&#x1f4d6;1. 单向通信&#xff08;单工通信&#xff09;2. 双向交替通信&#xff08;半双工通信&#xff09;3. 双向同时通信&#xff08;全双工通…

当AI遇上终端:Gemini CLI的技术魔法与架构奥秘

"代码不仅仅是指令的集合&#xff0c;更是思想的载体。当AI与终端相遇&#xff0c;会碰撞出怎样的火花&#xff1f;" 在这个AI技术日新月异的时代&#xff0c;Google推出的Gemini CLI无疑是一颗璀璨的明星。它不仅仅是一个命令行工具&#xff0c;更是一个将人工智能无…

ViLU: Learning Vision-Language Uncertainties for Failure Prediction

研究方向&#xff1a;Image Captioning1. 论文介绍本文提出ViLU&#xff08;Vision-Language Uncertainties&#xff09;&#xff0c;一个用于学习视觉语言不确定性量化&#xff08;UQ&#xff09;和检测视觉语言模型故障的事后框架。使用VLMs进行量化&#xff08;UQ&#xff0…

数据集笔记:百度地图高德地图坐标互转

1 为什么会有高德坐标系和百度坐标系&#xff1f;根据《测绘法》和国家保密法规&#xff0c;在中国大陆范围内的地理坐标数据必须做加密处理&#xff0c;不允许直接使用 WGS84&#xff08;openstreetmap&#xff09;所以出现了GCJ-02 和 BD-09高德、腾讯、谷歌中国都遵循 GCJ-0…

SkyWalking高效线程上下文管理机制:确保调用链中traceId来自同一个请求

SkyWalking Agent 能确保获取到“正确”的 traceId,其核心在于它建立并维护了一套高效的线程上下文管理机制。这套机制确保了即使在复杂的多线程、异步环境下,也能将正确的上下文(包含 traceId)与当前正在执行的代码逻辑关联起来。 其工作原理可以概括为下图所示的流程: …

Kafka-Eagle安装

目录Eagle环境安装Mysql环境准备Kafka环境准备Eagle安装Kafka-Eagle框架可以监控Kafka集群的整体运行情况&#xff0c;在生产环境中经常使用 Eagle环境安装 Mysql环境准备 Eagle的安装依赖于Mysql&#xff0c;Mysql主要用来存储可视化展示的数据 将mysql文件夹及里面所有内…

Matlab系列(005) 一 归一化

目录1、前言2、什么是归一化&#xff1f;3、为什么要进行归一化4、归一化方法详解与Matlab实现5、总结1、前言 ​   归一化技术是数据预处理的核心环节&#xff0c;本文将深度解析主流归一化方法&#xff0c;提供可复现Matlab代码&#xff0c;并探讨其在各领域中的应用场景。…

【K8s】整体认识K8s之namespace

命名空间将资源划分为相互隔离的组。kubectl get namespace/ns系统默认创建四个namespace&#xff0c;分别是default、kube-node-lease、kube-public、kube-system。default 没有指明使用其它命名空间的对象所使用的默认命名空间、kube-system 系统创建对象所使用的命名空间。…

rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(十八) 使用表格

使用表格egui_extras::TableBuilder // Cargo.toml [dependencies] eframe "0.32.1" egui "0.32.1" egui_extras "0.32.1"egui_extras::Column::auto() 列宽根据内容自动计算.resizable(true) 允许用户手动拖动调整列宽 fn main() -> efra…

【C#】构造函数实用场景总结

文章目录前言一、构造函数是什么&#xff1f;二、构造函数的用法1.初始化对象&#xff0c;避免无效状态2 初始化静态成员3 构造函数重载4.构造函数链5. 单例模式&#xff0c;多次实例化保持一个对象6. 依赖注入7. 初始化只读对象前言 构造函数是我们平常编程里经常能碰到的老伙…

LLM预训练架构全解析:从零构建一个语言世界的“操作系统”

导读&#xff1a;作为开发者&#xff0c;我们每天都在import或#include各种库&#xff0c;我们信任这些由无数代码构成的底层依赖。那么&#xff0c;当我们调用一个LLM时&#xff0c;它所依赖的那个更底层的、无形的**“语言操作系统”**&#xff0c;又是如何被“编译”出来的&…