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

LeetCode 2760 最长奇偶性

🔥 找出最长交替子数组:奇偶交替且偶数开头的子数组问题

🎯 题目描述

给定一个整数数组 nums 和一个整数 threshold,找出满足以下条件的最长子数组

  1. 偶数开头:子数组的第一个元素是偶数(nums[l] % 2 == 0)。
  2. 奇偶交替:相邻元素奇偶性不同(nums[i] % 2 != nums[i+1] % 2)。
  3. 元素不超限:所有元素 ≤ threshold

返回子数组的长度,若不存在符合条件的子数组,返回 0。

🌰 典型示例

输入数组输出解释
[3, 2, 5, 4], 53子数组 [2, 5, 4] 满足所有条件
[1, 2], 21子数组 [2] 满足条件
[2, 3, 4, 5], 43子数组 [2, 3, 4] 满足条件

🧠 思路分析

✨ 核心观察

  1. 偶数起点:子数组必须以偶数开头,因此遍历数组时,仅当遇到偶数且 ≤ threshold 时,才尝试扩展子数组。
  2. 奇偶交替:每次扩展子数组时,检查当前元素与前一个元素的奇偶性是否不同。
  3. 阈值过滤:任何元素超过 threshold 时,立即终止当前子数组的扩展。

🚀 算法策略

  • 双指针法:使用 start 标记子数组起点,i 作为遍历指针。
  • 单次遍历:外层循环遍历所有可能的起点,内层循环扩展子数组直到不满足条件。
  • 状态维护:仅需记录当前子数组的长度和奇偶性状态,空间复杂度为 O(1)

💻 代码实现(Java)

基础版(暴力枚举)

class Solution {
    public int longestAlternatingSubarray(int[] nums, int threshold) {
        int maxLength = 0;
        int n = nums.length;
        
        for (int start = 0; start < n; start++) {
            // 检查起点:偶数且 ≤ threshold
            if (nums[start] % 2 != 0 || nums[start] > threshold) {
                continue;
            }
            
            int currentLength = 1; // 起点本身长度为 1
            for (int i = start + 1; i < n; i++) {
                // 检查当前元素:奇偶交替且 ≤ threshold
                if (nums[i] % 2 != nums[i-1] % 2 && nums[i] <= threshold) {
                    currentLength++;
                } else {
                    break; // 不满足条件,终止扩展
                }
            }
            
            maxLength = Math.max(maxLength, currentLength); // 更新最长长度
        }
        
        return maxLength;
    }
}

优化版(双指针法)

class Solution {
    public int longestAlternatingSubarray(int[] nums, int threshold) {
        int maxLength = 0;
        int start = 0, i = 0; // 双指针:start 记录起点,i 遍历数组
        
        while (i < nums.length) {
            start = i; // 尝试以 i 为起点
            i++;
            
            // 起点必须是偶数且 ≤ threshold
            if (nums[start] % 2 != 0 || nums[start] > threshold) {
                continue;
            }
            
            // 扩展子数组直到不满足条件
            while (i < nums.length && 
                   nums[i] % 2 != nums[i-1] % 2 && 
                   nums[i] <= threshold) {
                i++;
            }
            
            // 更新最长长度(i - start 为当前子数组长度)
            maxLength = Math.max(maxLength, i - start);
        }
        
        return maxLength;
    }
}

📊 复杂度分析

算法时间复杂度空间复杂度
基础版O(n²)O(1)
双指针优化版O(n)O(1)

✨ 优化点

  • 双指针优化:通过单次遍历(每个元素最多访问 2 次),将时间复杂度从 O (n²) 优化到 O (n)。
  • 状态压缩:无需记录中间状态,仅用指针和长度变量即可完成计算。

📝 关键步骤解析

  1. 起点检查

    • 仅当元素是偶数且 ≤ threshold 时,作为子数组起点(nums[start] % 2 == 0 && nums[start] ≤ threshold)。
  2. 扩展子数组

    • 从起点开始,逐个检查后续元素:
      • 奇偶交替(nums[i] % 2 != nums[i-1] % 2)。
      • 元素 ≤ thresholdnums[i] ≤ threshold)。
    • 满足条件则延长子数组,否则终止扩展。
  3. 更新结果

    • 每次扩展结束后,计算当前子数组长度(i - start),并更新最长长度。

🧪 示例解析(以优化版代码为例)

示例 1:nums = [3, 2, 5, 4]threshold = 5

  1. 起点 start=1(元素 2,偶数且 ≤5)
    • 扩展子数组:
      • i=2(5,奇,与前偶不同,≤5 → 长度 2)。
      • i=3(4,偶,与前奇不同,≤5 → 长度 3)。
    • 最长长度更新为 3

示例 2:nums = [1, 2]threshold = 2

  1. 起点 start=1(元素 2,偶数且 ≤2)
    • 无后续元素,长度 1

示例 3:nums = [2, 3, 4, 5]threshold = 4

  1. 起点 start=0(元素 2,偶数且 ≤4)
    • 扩展子数组:
      • i=1(3,奇,与前偶不同,≤4 → 长度 2)。
      • i=2(4,偶,与前奇不同,≤4 → 长度 3)。
      • i=3(5,>4 → 终止)。
    • 最长长度 3

❗ 边界条件处理

  1. 全奇数数组:无符合条件的子数组,返回 0
  2. 元素超过阈值:遇到超过阈值的元素,立即终止当前子数组扩展。
  3. 单个元素:若元素是偶数且 ≤阈值,长度为 1

🌟 总结

✨ 核心条件

  • 偶数开头 + 奇偶交替 + 元素不超限

🚀 最优解法

  • 双指针遍历:单次扫描完成,时间复杂度 O (n)。
  • 关键技巧:利用指针标记起点,动态扩展子数组,避免重复计算。

💡 同类问题扩展

  • 允许奇数开头:修改起点条件为奇数。
  • 奇偶连续(非交替):检查相邻元素奇偶性相同。

📚 参考资料

  • LeetCode 原题:最长交替子数组
  • 算法思想:双指针法、贪心策略。

🎨 可视化流程图(双指针移动过程)

初始化:start=0, i=0, maxLength=0  
↓  
遍历数组:  
  if 起点合法(偶数且 ≤ threshold):  
    扩展子数组直到不满足条件(奇偶交替且 ≤ threshold)  
    更新 maxLength(i - start)  
↓  
返回 maxLength  

✨ 博客排版建议

  1. 标题分层:使用 ###### 区分章节(如**🔥 标题**、🎯 题目描述)。
  2. 代码高亮:使用 Java 代码块,标注关键注释(如起点检查、扩展条件)。
  3. 表格对比:用表格展示基础版与优化版的复杂度差异。
  4. 互动问题:在结尾提问:“如何处理包含负数的数组?(提示:奇偶性判断与负数无关)”。

通过以上结构,博客兼顾可读性技术性,适合算法学习者理解双指针法的应用。可补充双指针移动动画示例执行流程图,进一步提升内容的直观性。

相关文章:

  • 英伟达与通用汽车深化合作,澳特证券am broker助力科技投资
  • NotePad++与Navicat工具的下载 完全免费无套路
  • 《索引江湖:B树索引与哈希索引的风云对决》
  • 【设计模式】责任链模式
  • 模型 阿米巴模式
  • 信息安全专业优秀毕业设计选题题目汇总:课题建议
  • react-create-app整合windicss
  • 计算机视觉(CV)技术的优势和挑战
  • 2025.3.26总结
  • Camera控制:你需要掌握的理论基础
  • 医院管理系统(源码)分享
  • TCP/IP的网络连接设备
  • 重生细胞全符文获取攻略
  • 基于Spring Boot的成绩管理系统后台实现
  • 【智能体】从一个聊天工作流了解LangGraph
  • LLM - R1 强化学习 DRPO 策略优化 DAPO 与 Dr. GRPO 算法 教程
  • Mean Shift 图像分割与 Canny 边缘检测教程
  • 如何使用动作捕捉系统训练人形机器人
  • Apache Iceberg 解析,一文了解Iceberg定义、应用及未来发展
  • Logback使用和常用配置
  • 比尔·盖茨:未来20年通过盖茨基金会捐出几乎全部财富,2045年底基金会停止运营
  • 公募基金改革八大要点:建立浮动管理费收取机制、降低规模排名考核权重
  • 中国证监会印发《推动公募基金高质量发展行动方案》
  • 央视315晚会曝光“保水虾仁”后,湛江4家涉事企业被罚超800万元
  • 住宿行业迎“最火五一”:数千家酒店连续3天满房,民宿预订量创历史新高
  • 媒体:南京秦淮区卫健委回应一医院涉嫌违规提供试管婴儿服务