检测相邻递增子数组 II - LeetCode 3350 解题思路与代码解析

检测相邻递增子数组 II - LeetCode 3350 解题思路与代码解析

在本篇博客中,我们将深入解析一道中等难度的算法题------检测相邻递增子数组 II。通过这道题,我们将学习如何高效地处理数组中的递增子数组问题,并理解解决该问题的最佳策略。

题目描述

给定一个由 n 个整数组成的数组 nums,请你找出 k 的最大值,使得存在两个相邻且长度为 k 的严格递增子数组。具体来说,需要检查是否存在从下标 ab (a < b) 开始的两个子数组,并满足下述全部条件:

  1. 这两个子数组 nums[a..a + k - 1]nums[b..b + k - 1] 都是严格递增的。
  2. 这两个子数组必须是相邻 的,即 b = a + k

子数组是数组中的一个连续非空的元素序列。

示例

示例 1:

复制代码
输入:nums = [2,5,7,8,9,2,3,4,3,1]
输出:3
解释:
从下标 2 开始的子数组是 [7, 8, 9],它是严格递增的。
从下标 5 开始的子数组是 [2, 3, 4],它也是严格递增的。
这两个子数组是相邻的,因此 3 是满足题目条件的最大 k 值。

示例 2:

复制代码
输入:nums = [1,2,3,4,4,4,4,5,6,7]
输出:2
解释:
从下标 0 开始的子数组是 [1, 2],它是严格递增的。
从下标 2 开始的子数组是 [3, 4],它也是严格递增的。
这两个子数组是相邻的,因此 2 是满足题目条件的最大 k 值。

提示

  • 2 <= nums.length <= 2 * 10^5
  • -10^9 <= nums[i] <= 10^9

解题思路

要找到满足条件的最大 k,即存在两个相邻且长度为 k 的严格递增子数组,我们需要有效地遍历数组,并跟踪每个严格递增子数组的长度。

关键点在于:

  1. 识别严格递增的子数组:我们需要遍历数组,识别出所有严格递增的子数组,并记录它们的长度。
  2. 检查相邻性:确保找到的两个子数组是相邻的,即第二个子数组紧跟在第一个子数组的后面。
  3. 寻找最大 k :在所有可能的相邻子数组对中,找到最大的 k 值。

为了实现上述目标,我们可以采用以下策略:

  • 遍历数组:逐个元素检查当前元素是否比前一个元素大,以确定是否延续了当前的递增子数组。
  • 记录递增子数组的长度:当遇到不再递增的元素时,记录当前递增子数组的长度,并重置计数器以开始新的子数组。
  • 比较相邻子数组的长度 :每次记录一个递增子数组的长度时,与之前一个子数组的长度进行比较,更新 k 的值。

代码解析

以下是解决该问题的 Python 代码实现:

python 复制代码
class Solution:
    def maxIncreasingSubarrays(self, nums: List[int]) -> int:
        n = len(nums)
        ans = pre_cnt = cnt = 0
        for i, x in enumerate(nums):
            cnt += 1
            # 如果当前元素是最后一个,或者下一个元素不再递增
            if i == n - 1 or x >= nums[i + 1]:
                # 计算可能的 k 值
                # cnt // 2 是因为需要两个子数组,每个至少长度 k
                # min(pre_cnt, cnt) 确保两个子数组长度一致
                ans = max(ans, cnt // 2, min(pre_cnt, cnt))
                pre_cnt = cnt
                cnt = 0
        return ans

代码详解

  1. 初始化变量

    • n:数组的长度。
    • ans:存储当前找到的最大 k 值。
    • pre_cnt:记录上一个严格递增子数组的长度。
    • cnt:当前正在计数的严格递增子数组的长度。
  2. 遍历数组

    • 使用 enumerate 函数遍历数组的每个元素及其索引。
    • 对于每个元素 x,将 cnt 增加 1,表示当前递增子数组长度增加。
  3. 检测递增子数组的结束

    • 如果当前元素是最后一个元素 (i == n - 1),或者当前元素不小于下一个元素 (x >= nums[i + 1]),则说明当前递增子数组结束。
  4. 更新最大 k

    • 计算 cnt // 2,因为需要两个子数组,每个至少长度 k
    • pre_cntcnt 的最小值,确保两个子数组的长度一致。
    • 更新 ans 为当前找到的最大值。
  5. 重置计数器

    • pre_cnt 更新为当前的 cnt,为下一个递增子数组做准备。
    • cnt 重置为 0,开始新的计数。
  6. 返回结果

    • 最终返回 ans,即满足条件的最大 k 值。

示例解析

示例 1

复制代码
输入:nums = [2,5,7,8,9,2,3,4,3,1]
  • 递增子数组识别:

    • [2,5,7,8,9] 长度为 5
    • [2,3,4] 长度为 3
    • [3] 长度为 1
    • [1] 长度为 1
  • 相邻子数组对:

    • [2,5,7,8,9][2,3,4]:k = min(5,3) = 3
  • 最大 k 为 3。

示例 2

复制代码
输入:nums = [1,2,3,4,4,4,4,5,6,7]
  • 递增子数组识别:

    • [1,2,3,4] 长度为 4
    • [4] 长度为 1
    • [4] 长度为 1
    • [4,5,6,7] 长度为 4
  • 相邻子数组对:

    • [1,2,3,4][4]:k = min(4,1) = 1
    • [4][4]:k = min(1,1) = 1
    • [4][4,5,6,7]:k = min(1,4) = 1
  • 最大 k 为 1。

注意 :在第二个示例中,虽然 [1,2,3,4][4,5,6,7] 都是严格递增的,但它们不是直接相邻的,因为中间有一个单独的 [4]

复杂度分析

  • 时间复杂度O(n),其中 n 是数组的长度。我们只需要遍历数组一次。
  • 空间复杂度O(1),只使用了常数级别的额外空间。
相关推荐
海的诗篇_1 小时前
移除元素-JavaScript【算法学习day.04】
javascript·学习·算法
自动驾驶小卡1 小时前
A*算法实现原理以及实现步骤(C++)
算法
Unpredictable2221 小时前
【VINS-Mono算法深度解析:边缘化策略、初始化与关键技术】
c++·笔记·算法·ubuntu·计算机视觉
编程绿豆侠1 小时前
力扣HOT100之多维动态规划:1143. 最长公共子序列
算法·leetcode·动态规划
珂朵莉MM1 小时前
2021 RoboCom 世界机器人开发者大赛-高职组(初赛)解题报告 | 珂学家
java·开发语言·人工智能·算法·职场和发展·机器人
fail_to_code2 小时前
递归法的递归函数何时需要返回值
算法
C137的本贾尼3 小时前
(每日一道算法题)二叉树剪枝
算法·机器学习·剪枝
吴声子夜歌3 小时前
OpenCV——Mat类及常用数据结构
数据结构·opencv·webpack
笑口常开xpr3 小时前
数 据 结 构 进 阶:哨 兵 位 的 头 结 点 如 何 简 化 链 表 操 作
数据结构·链表·哨兵位的头节点