原理与步骤
问题分析
将数组重新排列,使得所有偶数位于偶数索引,奇数位于奇数索引。要求时间复杂度为 O(n) 且空间复杂度为 O(1)。
解决思路
- 单指针遍历偶数索引:遍历所有偶数索引
i
,若该位置的元素是奇数,则需交换。 - 双指针修正奇偶位置:维护一个奇数索引指针
oddindex
,找到该指针位置上的偶数元素,与当前偶数索引上的奇数元素交换。
图示法步骤(以输入 nums = [4,2,5,7]
为例)
步骤 | 操作说明 | 数组状态 |
---|---|---|
i=0 | nums[0]=4 (偶数),无需处理 | [4, 2, 5, 7] |
i=2 | nums[2]=5 (奇数),触发交换 | |
找oddindex | oddindex=1 ,nums[1]=2 (偶数) | |
交换后 | nums[2] 与nums[1] 交换 | [4, 5, 2, 7] |
修正后的代码程序与注释
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
vector<int> sortArrayByParityII(vector<int>& nums) {
int oddindex = 1; // 奇数索引指针,初始指向1
for (int i = 0; i < nums.size(); i += 2) { // 遍历偶数索引
if (nums[i] % 2 == 1) { // 当前偶数索引位置是奇数,需要交换
// 找到奇数索引位置上的偶数
while (oddindex < nums.size() && nums[oddindex] % 2 == 1) {
oddindex += 2; // 跳过已经是奇数的位置
}
// 交换,确保两个位置都符合条件
swap(nums[i], nums[oddindex]);
}
}
return nums;
}
int main() {
vector<int> nums;
string line;
getline(cin, line);
istringstream iss(line);
int num;
while (iss >> num) nums.push_back(num); // 读取输入数组
vector<int> ans = sortArrayByParityII(nums);
for (int num : ans) cout << num << " ";
return 0;
}
关键代码注释
-
遍历偶数索引
for (int i = 0; i < nums.size(); i += 2)
只处理偶数索引位置,确保这些位置最终为偶数。
-
触发交换条件
if (nums[i] % 2 == 1)
当偶数索引位置是奇数时,需要与奇数索引位置的偶数交换。
-
寻找可交换的奇数索引
while (oddindex < nums.size() && nums[oddindex] % 2 == 1)
跳过所有奇数索引位置上的奇数,找到第一个偶数。
时间复杂度与空间复杂度
- 时间复杂度:
- 每个元素最多被访问两次 → O(n)。
- 空间复杂度:
- 仅用常量变量 → O(1)。
总结
- 核心逻辑:通过维护两个指针,确保偶数索引位置为偶数,奇数索引位置为奇数。
- 修正点:原代码增加越界检查
oddindex < nums.size()
,避免无效输入导致的崩溃。 - 优点:
- 单次遍历,高效处理大规模数据。
- 逻辑简洁,无额外空间占用。
- 边界处理:
- 输入数组必须满足偶数数目等于
n/2
,奇数数目等于n/2
。
- 输入数组必须满足偶数数目等于
- 适用场景:需要高效原地调整数组奇偶位置的问题。