当前位置: 首页 > article >正文

力扣周赛:第424场周赛

👨‍🎓作者简介:爱好技术和算法的研究生
🌌上期文章:力扣周赛:第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 。

模拟题,没啥好说的

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]–,即可维护这部分关系了。

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了一发。

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.kler.cn/a/399071.html

相关文章:

  • nuget 管理全局包、缓存和临时文件夹
  • WebRTC视频 02 - 视频采集类 VideoCaptureModule
  • 牛客题库 21738 牛牛与数组
  • 【Java多线程】单例模式(饿汉模式和懒汉模式)
  • java常用工具包介绍
  • react中如何在一张图片上加一个灰色蒙层,并添加事件?
  • 【机器学习】朴素贝叶斯算法
  • 基于K8S1.28.2实验rook部署ceph
  • FPGA开发-逻辑分析仪的应用-数字频率计的设计
  • 关于做完 C# 项目的问题总结
  • STM32设计智能翻译手势识别加算法系统
  • 基于OpenCV的自制Python访客识别程序
  • Java基础-内部类与异常处理
  • Intern大模型训练营(八):Llamaindex RAG 实践
  • python核心语法
  • 树莓派(Raspberry Pi)picotool
  • RHCSA学习超详细知识点2命令篇
  • 开源vs闭源:你更看好哪一方?
  • 徒步中补给问题——贪心算法
  • 畜牧定位器
  • Linux 硬链接和软链接的使用场景有哪些?
  • [C/C++] 定位新表达式 placement new
  • Android 中的 Zygote 和 Copy-on-Write 机制详解
  • React 中如何解析字符串中的 html 结构
  • SpringBoot整合FreeMarker生成word表格文件
  • [Admin] Dashboard Filter for Mix Report Types