目录
问题背景
在编程的世界里,数组排序问题一直是经典中的经典。今天我们要解决的是一个有趣的变种:按奇偶排序数组。题目要求我们将一个整数数组中的所有偶数元素移动到数组的前面,后跟所有奇数元素。看似简单,但如何高效地实现却是一个值得深思的问题。
题目解析
假设我们有一个数组 [3, 1, 2, 4]
,按照题目要求,我们需要将偶数元素(2 和 4)放到前面,奇数元素(3 和 1)放到后面。最终的输出应该是 [2, 4, 3, 1]
或 [2, 3, 4, 1]
等,只要偶数在前、奇数在后即可。
解题思路
暴力解法
最直观的思路是创建两个数组:一个存储偶数,一个存储奇数。遍历原数组,将偶数放入第一个数组,奇数放入第二个数组,最后将两个数组拼接起来。这种方法简单易懂,但需要额外的空间来存储两个数组,空间复杂度为 O(n)。
双指针法
有没有更高效的方法呢?答案是肯定的!我们可以使用 双指针法,在原地完成排序,空间复杂度降为 O(1)。
双指针法的核心思想是:
用一个指针(
even
)记录下一个偶数应该放置的位置。遍历数组,每当遇到偶数时,将其与
even
指针位置的元素交换,并将even
指针向前移动一位。
这种方法只需要一次遍历,时间复杂度为 O(n),空间复杂度为 O(1),非常高效。
代码实现
下面是基于双指针法的代码实现:
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortArrayByParity = function (nums) {
let even = 0; // 偶数索引
for (let i = 0; i < nums.length; i++) {
// 如果当前元素是偶数
if (nums[i] % 2 === 0) {
// 交换当前元素和偶数索引处的元素
let temp = nums[even];
nums[even] = nums[i];
nums[i] = temp;
even++;
}
}
return nums;
};
console.log(sortArrayByParity([3, 1, 2, 4])); // 输出可能是 [2, 4, 3, 1]
代码解析
初始化指针:
even
指针初始化为 0,表示第一个偶数应该放在数组的起始位置。遍历数组:用
i
指针从头到尾遍历数组。判断偶数:如果
nums[i]
是偶数,就与even
指针位置的元素交换。移动指针:交换后,
even
指针向前移动一位,准备放置下一个偶数。
算法效率
时间复杂度:O(n),因为只需要遍历数组一次。
空间复杂度:O(1),因为不需要额外的空间存储。
实际应用场景
这种按奇偶排序的算法在实际开发中有很多应用场景,比如:
数据分类:将数据按照某种属性(如奇偶性)进行分类。
性能优化:在某些场景下,将特定类型的元素集中存放可以提高访问效率。
总结
通过双指针法,我们优雅地解决了按奇偶排序数组的问题。这种方法不仅高效,而且易于理解。希望这篇文章能帮助你更好地掌握这种经典算法!