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

力扣 922. 按奇偶排序数组 II :双指针原地交换

目录

题目解析

算法思路:双指针原地交换

关键步骤:

正确性证明:

示例详解

复杂度分析

对比其他解法

总结


题目解析

题目要求将非负整数数组重新排列,使得所有偶数元素位于偶数索引(0, 2, 4, ...),所有奇数元素位于奇数索引(1, 3, 5, ...)。题目保证至少存在一个有效解,且答案不唯一。

示例输入输出

  • 输入:nums = [4,2,5,7]

  • 输出:[4,5,2,7](或其他合法排列)


算法思路:双指针原地交换

核心思想是通过双指针分别跟踪偶数索引和奇数索引,逐步将元素调整到正确的位置。

关键步骤:
  1. 初始化双指针

    • even 指针从 0 开始,步长为 2,用于寻找偶数索引处的奇数元素。

    • odd 指针从 1 开始,步长为 2,用于寻找奇数索引处的偶数元素。

  2. 循环处理

    • 若 even 指向的元素是偶数,说明当前位置正确,even 后移 2 步。

    • 若 odd 指向的元素是奇数,说明当前位置正确,odd 后移 2 步。

    • 否则,交换 even 和 odd 指向的元素,这样两个位置的元素均满足条件。

  3. 终止条件

    • 当任意指针超出数组长度时,所有元素已正确排列。

正确性证明:

每次交换操作至少修复两个位置的错误(一个偶数的位置和一个奇数的位置),由于题目保证输入有解,算法最终会将所有元素归位。

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortArrayByParityII = function(nums) {
    let even = 0; // 偶数索引
    let odd = 1; // 奇数索引
    while (even < nums.length && odd < nums.length) {
        if (nums[even] % 2 === 0) { // 如果偶数索引处的数字是偶数
            even += 2; // 移动到下一个偶数索引
        } else if (nums[odd] % 2 === 1) { // 如果奇数索引处的数字是奇数
            odd += 2; // 移动到下一个奇数索引
        } else { // 如果偶数索引处的数字是奇数且奇数索引处的数字是偶数
            [nums[even], nums[odd]] = [nums[odd], nums[even]]; // 交换它们
        }
    }
    return nums; // 返回排序后的数组
};

console.log(sortArrayByParityII([4, 2, 5, 7]));

示例详解

以输入 nums = [4,2,5,7] 为例:

  1. 初始状态

    • even = 0odd = 1

    • 检查 nums[0] = 4(偶数),even 移动到 2

  2. 第二轮循环

    • nums[2] = 5(奇数),检查 odd = 1 处的 nums[1] = 2(偶数)。

    • 交换两者,数组变为 [4,5,2,7]

  3. 指针更新

    • even 移动到 4,超出数组长度,循环终止。

最终结果为 [4,5,2,7],所有偶数位于偶数索引,奇数位于奇数索引。


复杂度分析

  • 时间复杂度:O(n),每个元素最多被访问一次。

  • 空间复杂度:O(1),原地交换,仅使用常数空间。


对比其他解法

  1. 额外空间法

    • 分别收集偶数和奇数,依次填充到偶数索引和奇数索引。

    • 时间复杂度 O(n),但空间复杂度 O(n)。

  2. 两次遍历法

    • 第一次处理偶数,第二次处理奇数,但实现较为繁琐。

当前的双指针法在时间和空间上均最优,适合大数据量的场景。


总结

通过双指针一次遍历,原地交换元素,该算法高效且优雅地解决了奇偶排序问题。理解双指针移动的条件和交换的动机是掌握此算法的关键。

http://www.dtcms.com/a/123181.html

相关文章:

  • 2025年第十八届“认证杯”数学中国数学建模网络挑战赛【ABCD题】思路分析
  • Java 实现 List<String> 与 String 互转
  • CentOS Stream release 9安装 MySQL(二)
  • 在Halcon的语义分割中,过度拟合解决方法
  • 什么是中性线、零线、地线,三相四线制如何入户用电
  • JVM底层详解
  • ANTLR v4 中文文档1:语法词典Grammar Lexicon部分
  • NginxWebUI:可视化 Nginx 配置管理工具,告别繁琐命令行!
  • 高并发内存池(三):PageCache(页缓存)的实现
  • Window代码向Linux平台移植问题汇总
  • pytorch TensorDataset与DataLoader类
  • GRBL运动控制算法(五)脉冲生成Bresenham算法
  • 基于 Spring Boot 瑞吉外卖系统开发(三)
  • HackMyVM - todd记录
  • 编译器bug ?
  • (十二)安卓开发中FrameLayout的使用方法详解
  • 在计算极限的时候泰勒公式到底展开到第几项
  • 阿里云CDN与DCDN主动推送静态资源至边缘服务器的ASP.NET WEB实例
  • KaiwuDB 数据库基本概念解析
  • 山东大学软件学院创新项目实训开发日志(9)之测试前后端连接
  • 计算机组成原理 原码乘法 补码乘法
  • 体验OceanBase的 并行导入功能
  • 631SJBH中小型企业的网络管理模式的方案设计
  • AI日报 - 2025年4月11日
  • 44、Spring Boot 详细讲义(一)
  • 共享内存(与消息队列相似)
  • 【Java面试系列】Spring Boot微服务架构下的分布式事务解决方案与性能优化详解 - 3-5年Java开发必备知识
  • Elasticsearch 系列专题 - 第五篇:集群与性能优化
  • P1359 洛谷 租用游艇
  • GPU NPU TPU的区别与联系