力扣周赛:第424场周赛

server/2024/11/19 5:00:40/

👨‍🎓作者简介:爱好技术和算法的研究生
🌌上期文章:力扣周赛>力扣周赛:第422场周赛
📚订阅专栏:力扣周赛>力扣周赛
希望文章对你们有所帮助

第一道题模拟题,第二道题经典拆分数组/线段树都可以做,这两个要是都不会那就是基础不行,需要差缺补漏了。第三题那个味太足了,一看那个答案的顺序性就知道要二分答案了,也很简单。

力扣周赛>力扣周赛:第424场周赛

  • 使数组元素等于零
  • 零数组变换 I
  • 零数组变换 II

使数组元素等于零

题目描述
给你一个整数数组 nums 。

开始时,选择一个满足 nums[curr] == 0 的起始位置 curr ,并选择一个移动 方向 :向左或者向右。

此后,你需要重复下面的过程:

  • 如果 curr 超过范围 [0, n - 1] ,过程结束。
  • 如果 nums[curr] == 0 ,沿当前方向继续移动:如果向右移,则 递增 curr ;如果向左移,则 递减 curr 。
  • 如果 nums[curr] > 0:
    • 将 nums[curr] 减 1 。
    • 反转 移动方向(向左变向右,反之亦然)。
    • 沿新方向移动一步。

如果在结束整个过程后,nums 中的所有元素都变为 0 ,则认为选出的初始位置和移动方向 有效 。

返回可能的有效选择方案数目。
示例1
在这里插入图片描述

示例2
输入:nums = [2,3,4,0,4,1,0]

输出:0

解释:
不存在有效的选择方案。

提示

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 100
  • 至少存在一个元素 i 满足 nums[i] == 0 。

模拟题,没啥好说的

java">class Solution {public int countValidSelections(int[] nums) {int ans = 0;for(int i = 0; i < nums.length; ++i){if(nums[i] == 0){int[] temp1 = new int[nums.length];int[] temp2 = new int[nums.length];for(int j = 0; j < nums.length; ++j){temp1[j] = nums[j];temp2[j] = nums[j];}if(check(temp1, i, 1))ans++;if(check(temp2, i, -1))ans++;}}return ans;}public boolean check(int[] nums, int cur, int dir){while(true){cur = cur + dir;if(cur < 0 || cur == nums.length)break;if(nums[cur] > 0){nums[cur]--;dir *= -1;}}for(int i = 0; i < nums.length; ++i){if(nums[i] != 0)return false;}return true;}
}

零数组变换 I

题目描述
给定一个长度为 n 的整数数组 nums 和一个二维数组 queries,其中 queries[i] = [li, ri]

对于每个查询 queries[i]:

  • 在 nums 的下标范围 [li, ri] 内选择一个下标子集。
  • 将选中的每个下标对应的元素值减 1。

零数组 是指所有元素都等于 0 的数组。

如果在按顺序处理所有查询后,可以将 nums 转换为 零数组 ,则返回 true,否则返回 false。

数组的 子集 是对数组元素的选择(可能为空)。
示例1
输入: nums = [1,0,1], queries = [[0,2]]

输出: true

解释:

  • 对于 i = 0:
    选择下标子集 [0, 2] 并将这些下标处的值减 1。
    数组将变为 [0, 0, 0],这是一个零数组。

示例2
输入: nums = [4,3,2,1], queries = [[1,3],[0,2]]

输出: false

解释:

  • 对于 i = 0:
    选择下标子集 [1, 2, 3] 并将这些下标处的值减 1。
    数组将变为 [4, 2, 1, 0]。
  • 对于 i = 1:
    选择下标子集 [0, 1, 2] 并将这些下标处的值减 1。
    数组将变为 [3, 1, 0, 0],这不是一个零数组。

提示

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 105
  • 1 <= queries.length <= 105
  • queries[i].length == 2
  • 0 <= li <= ri < nums.length

很显然是拆分数组,直接维护一个f,其中f[i]表示nums[i]共处在哪些区间中,只要f[i] >= nums[i],则说明肯定是可以在queries中将其处理到0。
所以问题转化为某个下标处在哪些区间中,对于每个query的起始点start和终止点end,只需要让f[start]++和f[end + 1]–,即可维护这部分关系了。

java">class Solution {public boolean isZeroArray(int[] nums, int[][] queries) {int[] f = new int[nums.length];for(int[] query : queries){int start = query[0], end = query[1];f[start]++;if(end + 1 >= nums.length)continue;f[end + 1]--;}int sum=0;for(int i = 0; i < nums.length; ++i){sum += f[i];if(nums[i] > sum)return false;}return true;}
}

零数组变换 II

题目描述
给你一个长度为 n 的整数数组 nums 和一个二维数组 queries,其中 queries[i] = [li, ri, vali]

每个 queries[i] 表示在 nums 上执行以下操作:

  • 将 nums 中 [li, ri] 范围内的每个下标对应元素的值 最多 减少 vali。
  • 每个下标的减少的数值可以独立选择。

零数组 是指所有元素都等于 0 的数组。

返回 k 可以取到的 最小非负 值,使得在 顺序 处理前 k 个查询后,nums 变成 零数组。如果不存在这样的 k,则返回 -1。
示例1
输入: nums = [2,0,2], queries = [[0,2,1],[0,2,1],[1,1,3]]

输出: 2

解释:

  • 对于 i = 0(l = 0, r = 2, val = 1):
    • 在下标 [0, 1, 2] 处分别减少 [1, 0, 1]。
    • 数组将变为 [1, 0, 1]。
  • 对于 i = 1(l = 0, r = 2, val = 1):
    • 在下标 [0, 1, 2] 处分别减少 [1, 0, 1]。
    • 数组将变为 [0, 0, 0],这是一个零数组。因此,k 的最小值为 2。

示例2
输入: nums = [4,3,2,1], queries = [[1,3,2],[0,2,1]]

输出: -1

解释:

  • 对于 i = 0(l = 1, r = 3, val = 2):
    • 在下标 [1, 2, 3] 处分别减少 [2, 2, 1]。
    • 数组将变为 [4, 1, 0, 0]。
  • 对于 i = 1(l = 0, r = 2, val = 1):
    • 在下标 [0, 1, 2] 处分别减少 [1, 1, 0]。
    • 数组将变为 [3, 0, 0, 0],这不是一个零数组。

提示

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 5 * 105
  • 1 <= queries.length <= 105
  • queries[i].length == 3
  • 0 <= li <= ri < nums.length
  • 1 <= vali <= 5

这个顺序性味太足了,直接二分答案是不会超时的,当然了你还是还想优化也可以,因为那个拆分数组肯定是可以在每次复用的时候被二分的。
记得特判一下,我没特判wa了一发。

java">class Solution {public int minZeroArray(int[] nums, int[][] queries) {int n = nums.length;int now = 0;for(int i = 0; i < n; ++i)now += nums[i];if(now == 0)return 0;int l = 0, r = queries.length - 1;while(l <= r){int mid = (l + r) >> 1;int[] f = new int[n];for(int i = 0; i <= mid; ++i){int start = queries[i][0], end = queries[i][1], val = queries[i][2];f[start] += val;if(end + 1 >= n)continue;f[end + 1] -= val;}int sum = 0;boolean flag = true;for(int i = 0; i < n; ++i){sum += f[i];if(nums[i] > sum){flag = false;break;}}if(!flag){l = mid + 1;}else{r = mid - 1;}}return l >= queries.length ? -1 : l + 1;}
}

http://www.ppmy.cn/server/143081.html

相关文章

<项目代码>YOLOv8 番茄识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

3D绘制动态爱心Matlab

代码1&#xff1a;动态爱心 function particleHeart1% 调整背景及比例axgca;hold onax.DataAspectRatio[1,1,1];ax.XLim[-25,25];ax.YLim[-25,20];ax.Color[0,0,0];ax.XColornone;ax.YColornone;set(gcf,Color,[0,0,0]);% 散点位置计算函数及扩散函数tFunc(n) rand([1,n]).*pi…

【计算机网络】TCP网络特点2

断开连接 四次挥手 原因 TCP 四次挥手是为了满足 TCP 连接的全双工特性:两个方向都可以自由传输 保证数据传输的完整性&#xff1a;两方都完成了数据发送和接收并且都同意断开连接 可靠地终止连接以及避免数据混淆和错误等需求:每个方向都需要单独确认导致四次挥手过程 这些…

matlab 读取csv

需要跳过第一行表头等信息 1、读取整个文件 csvread(FILENAME)%文件路径 文件名2、指定起始位置 csvread(FILENAME, R, C)%从文件的第R行和第C列开始读取数据 逗号分开3、指定数据范围 csvread(FILENAME, R, C, [R1 C1 R2 C2])%读取从(R1, C1)到(R2, C2)范围内的数据注意&am…

SpringBoot - Async异步处理

目录 一、定义 1、同步调用 2、异步调用 二、示例 1、同步调用 执行类&#xff1a; 测试用例&#xff1a; 运行结果&#xff1a; 2、异步调用 &#xff08;1&#xff09;普通调用 执行类&#xff1a; 测试用例&#xff1a; 运行结果&#xff1a; &#xff08;2&…

4.2 Android NDK 基础概念

1 JavaVM和JNIEnv JNI 定义了两个关键数据结构&#xff0c;JavaVM和JNIEnv。这两者本质上都是指向函数表指针的指针。&#xff08;在 C 版本中&#xff0c;它们是具有指向函数表的指针的类&#xff0c;以及指向该表的每个 JNI 函数的成员函数。&#xff09;JavaVM提供了“调用接…

第九部分 :1.STM32之通信接口《精讲》(USART,I2C,SPI,CAN,USB)

本芯片使用的是STM32F103C8T6型号 STM32F103C8T6是STM32F1系列中的一种较常用的低成本ARM Cortex-M3内核MCU&#xff0c;具有丰富的通信接口&#xff0c;包括USART、SPI、I2C等。下面是该芯片上通信接口的管脚分布、每个接口的工作模式、常用应用场景和注意事项。 1. USART (通…

python贪心算法实现(纸币找零举例)

目录 问题描述 贪心策略 Python代码实现 代码解释 示例输出 注意事项 问题描述 给定一组纸币面值和一个目标金额&#xff0c;找出用最少数量的纸币来找零的方法。 贪心策略 每次选择面值最大的纸币&#xff0c;直到无法继续选择为止。 Python代码实现 def min_bills…