Leecode刷题C语言之或值至少K的最短子数组①

执行结果:通过

执行用时和内存消耗如下:

复制代码
int minimumSubarrayLength(int* nums, int numsSize, int k) {
    int left = 0;
    int right = 0;
    int currentOr = 0;
    int minLength = INT_MAX;

    while (right < numsSize) {
        // 扩展窗口,添加新元素到 currentOr
        currentOr |= nums[right];

        // 当 currentOr >= k 时,尝试收缩窗口
        while (currentOr >= k && left <= right) {
            // 更新最短长度
            if (right - left + 1 < minLength) {
                minLength = right - left + 1;
            }
            // 移除左端点元素,并更新 currentOr
            int tempOr = 0;
            for (int i = left + 1; i <= right; ++i) {
                tempOr |= nums[i];
            }
            currentOr = tempOr;
            ++left;
        }

        ++right;
    }

    // 检查是否有符合条件的子数组
    return minLength == INT_MAX ? -1 : minLength;
}

解题思路:

这段代码的解题思路旨在寻找一个最短的连续子数组,使得该子数组中所有数字的按位或(bitwise OR)结果大于等于给定的整数 k。以下是详细的解题步骤:

  1. 初始化变量
    • leftright 分别表示当前考虑的子数组的左右边界,初始都设为 0。
    • currentOr 用于存储当前子数组内所有元素的按位或结果,初始化为 0。
    • minLength 用于记录符合条件的最短子数组的长度,初始化为 INT_MAX(一个非常大的数,表示初始时未找到符合条件的子数组)。
  2. 遍历数组
    • 使用一个 while 循环遍历数组,条件是 right < numsSize,即右边界未超出数组长度。
  3. 扩展窗口
    • 在每次循环中,首先通过 currentOr |= nums[right] 将当前元素加入到 currentOr 中,扩展窗口的右边界。
  4. 尝试收缩窗口
    • 检查 currentOr 是否大于等于 k。如果是,说明当前窗口(或更大的窗口)可能包含符合条件的子数组。
    • 进入一个内层 while 循环,条件是 currentOr >= kleft <= right。这个循环尝试收缩窗口的左边界,以找到最短的可能子数组。
  5. 更新最短长度
    • 在内层循环中,如果当前窗口的长度(right - left + 1)小于 minLength,则更新 minLength
  6. 收缩窗口并更新 currentOr
    • 为了收缩窗口,需要从当前窗口中移除左边界的元素。代码中的实现方式是通过一个循环从 left + 1right 重新计算 currentOr(这里有一个效率问题,下面会提到)。
    • 更新 currentOr 为不包含左边界元素的新值。
    • left 右移一位,继续尝试收缩窗口。
  7. 继续扩展窗口
    • 完成内层循环后,继续扩展外层循环的右边界,即将 right 右移一位。
  8. 返回结果
    • 循环结束后,检查 minLength 是否仍为 INT_MAX。如果是,说明没有找到符合条件的子数组,返回 -1
    • 否则,返回 minLength,即符合条件的最短子数组的长度。

效率问题

  • 在收缩窗口的过程中,代码通过一个循环重新计算 currentOr,这实际上是不必要的。可以通过记录移除元素之前的 currentOr 值和移除元素本身,然后使用按位运算直接更新 currentOr,从而提高效率。

优化思路

  • 可以使用一个变量来跟踪上一次计算 currentOr 时左边界元素对 currentOr 的贡献,这样在移除左边界元素时,可以直接通过按位运算减去该贡献,而无需重新计算整个窗口的 currentOr
相关推荐
聪明的笨猪猪17 分钟前
Java Spring “IOC + DI”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
ThisIsMirror20 分钟前
CompletableFuture并行任务超时处理模板
java·windows·python
Young_Zn_Cu1 小时前
LeetCode刷题记录(持续更新中)
算法·leetcode
天选之女wow1 小时前
【代码随想录算法训练营——Day31】贪心算法——56.合并区间、738.单调递增的数字、968.监控二叉树
算法·leetcode·贪心算法
lixinnnn.1 小时前
贪心:火烧赤壁
数据结构·c++·算法
小小前端_我自坚强1 小时前
前端算法相关详解
前端·算法
珹洺1 小时前
Java-Spring入门指南(二十一)Thymeleaf 视图解析器
java·开发语言·spring
源码集结号1 小时前
一套智慧工地云平台源码,支持监管端、项目管理端,Java+Spring Cloud +UniApp +MySql技术开发
java·mysql·spring cloud·uni-app·源码·智慧工地·成品系统
EnCi Zheng1 小时前
Spring Security 最简配置完全指南-从入门到精通前后端分离安全配置
java·安全·spring
程序员小假1 小时前
为什么这些 SQL 语句逻辑相同,性能却差异巨大?
java·后端