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
相关推荐
We་ct2 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
JAVA面经实录9176 小时前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
王老师青少年编程6 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮7 小时前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
天疆说7 小时前
【哈密顿力学】深入解读航天器交会最优控制中的Hamilton函数
人工智能·算法·机器学习
许彰午8 小时前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存
wuweijianlove8 小时前
关于算法设计中的代价函数优化与约束求解的技术7
算法
leoufung8 小时前
LeetCode 149: Max Points on a Line - 解题思路详解
算法·leetcode·职场和发展
样例过了就是过了8 小时前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划
HXDGCL8 小时前
矩形环形导轨:自动化循环线的核心运动单元解析
运维·算法·自动化