题目:
给定一个非负整数数组 nums
, nums
中一半整数是 奇数 ,一半整数是 偶数 。
对数组进行排序,以便当 nums[i]
为奇数时,i
也是 奇数 ;当 nums[i]
为偶数时, i
也是 偶数 。
示例 1:
输入:nums = [4,2,5,7] 输出:[4,5,2,7] 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
示例 2:
输入:nums = [2,3] 输出:[2,3]
提示:
2 <= nums.length <= 2 * 104
nums.length
是偶数nums
中一半是偶数0 <= nums[i] <= 1000
进阶:可以不使用额外空间解决问题吗?
题解:
这道题目的核心要求是将数组 nums
重新排列,使得数组中位于奇数位置的元素也是奇数,而位于偶数位置的元素也是偶数。即:
nums[0]
,nums[2]
,nums[4]
, ... 是偶数nums[1]
,nums[3]
,nums[5]
, ... 是奇数
这里的“位置”是基于编程语言中常用的从零开始计数的索引。
我们可以通过一种简单的方法来实现这个要求:
- 初始化两个指针,
evenIndex
和oddIndex
,分别用于追踪下一个应该放置的偶数和奇数的位置。 evenIndex
从 0 开始,每次增加 2;oddIndex
从 1 开始,每次增加 2。- 遍历数组
nums
,根据当前元素是奇数还是偶数,我们放在相应的位置,并移动指针。 - 当两个指针都超出数组长度时,排序完成。
考虑到进阶问题,即不使用额外空间进行排序,我们需要在原数组上进行操作。这样,我们可以在遇到不在正确位置的元素时,寻找并与其交换正确位置上的元素。 具体实现时,可以用循环或者递归的方式来进行。
代码:
class Solution {
public int[] sortArrayByParityII(int[] nums) {
int n = nums.length;
int evenIndex = 0; // 初始化偶数位置指针
int oddIndex = 1; // 初始化奇数位置指针
while (evenIndex < n && oddIndex < n) {
// 同时找到错位的偶数和奇数,然后交换。
if (nums[evenIndex] % 2 == 1 && nums[oddIndex] % 2 == 0) {
// 交换偶数位置上的奇数和奇数位置上的偶数
int temp = nums[evenIndex];
nums[evenIndex] = nums[oddIndex];
nums[oddIndex] = temp;
evenIndex += 2;
oddIndex += 2;
} else {
// 如果偶数位置正确,移动到下一个偶数位置
if (nums[evenIndex] % 2 == 0) {
evenIndex += 2;
}
// 如果奇数位置正确,移动到下一个奇数位置
if (nums[oddIndex] % 2 == 1) {
oddIndex += 2;
}
}
}
return nums; // 返回排序后的数组
}
}
知识点概览:
-
数组操作: 这是最基本也是最重要的知识点。代码中涉及到对数组的遍历和基于索引对数组元素的访问和修改。
-
双指针技术: 双指针是一种常见的用于解决数组和链表问题的技术。在这个问题中,我们使用了两个指针(
evenIndex
和oddIndex
)来分别追踪下一个应放置偶数和奇数的位置。这两个指针按照不同的规则移动(一个跳两格,一个跳两格),分别处理偶数和奇数情况。 -
奇偶性检查: 使用
%
模运算符检查一个数字的奇偶性。在代码中,num % 2 == 0
用于检查数字是否为偶数,num % 2 == 1
用于检查数字是否为奇数。 -
条件控制: 使用
if-else
语句结构进行条件分支控制。代码中使用if-else
来根据指针指向的元素的奇偶性决定是否进行交换,以及如何移动指针。 -
循环控制: 使用
while
循环来重复检查和交换数组直至整个数组被正确排序。这里的循环确保了只要evenIndex
和oddIndex
指针未越界,就一直进行检查和可能的交换操作。 -
变量交换: 通过使用临时变量
temp
来交换两个元素的值。这是基本的算法技巧,即使用temp
存储一个元素的值,然后将另一个元素的值赋给这个元素,接着用temp
的值更新另一个元素。
知识点类别 | 详细描述 |
---|---|
数组操作 | - 遍历数组。 - 基于索引对数组元素进行访问和修改。 |
双指针技术 | - 使用双指针(evenIndex 和 oddIndex)分别追踪偶数和奇数的位置。 - 指针按不同规则移动,分别处理偶数和奇数元素。 |
奇偶性检查 | - 使用 % 模运算符检查数字的奇偶性。- num % 2 == 0 检查偶数。- num % 2 == 1 检查奇数。 |
条件控制 | - 通过 if-else 语句进行条件分支控制。 - 依据元素的奇偶性决定是否交换元素,以及如何移动指针。 |
循环控制 | - 使用 while 循环,确保 evenIndex 和 oddIndex 指针未越界时,持续进行检查和交换操作。 |
变量交换 | - 使用临时变量 temp 交换两个元素的值。 - 通用的算法技巧来交换变量值。 |
2024.5.10