难度简单256
给定一个非负整数数组 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 * 104nums.length是偶数nums中一半是偶数0 <= nums[i] <= 1000
进阶:可以不使用额外空间解决问题吗?
解题方法:双指针
既然题目说到不适用额外空间解决问题,那么肯定是在原数组上操作,可以考虑用双指针。
最初我的思路是这样子的:
- 遍历 nums,用 left 表示需要变换的位置下标,用 right 来往后遍历查找替换 left 处元素的下标
- 若 nums[left] 是偶数且下标为奇数,则让 right 往右走直到找到值为奇数为止,然后与 left 处交换元素
- 若 nums[left] 是奇数且下标为偶数,则让 right 往右走直到找到值偶数为止,然后与 left 处交换元素
- 若下标与值是匹配的,则不需要交换,让 left 和 right 同时向右走
- 遍历完 nums 后返回即可
class Solution {
public:
vector<int> sortArrayByParityII(vector<int>& nums) {
int left = 0;
int right = 0;
while(right < nums.size())
{
// 下标为奇数,值为偶数
if(left % 2 != 0 && nums[left] % 2 == 0)
{
while(right < nums.size() && nums[right] % 2 == 0)
{
right++;
}
swap(nums[right], nums[left]);
right = ++left;
}
// 下标为偶数,值为奇数
else if(left % 2 == 0 && nums[left] % 2 != 0)
{
while(right < nums.size() && nums[right] % 2 != 0)
{
right++;
}
swap(nums[right], nums[left]);
right = ++left;
}
else
{
left = ++right;
}
}
return nums;
}
};优化
虽然这样子也通过了,但是时间复杂度好像稍微高了一点,所以查看了一下题解,好像可以优化一下:
- 用 odd 为维护奇数下标,用 even 来维护偶数下标,它们往右走的时候每次只需要 +=2 即可!
- 遍历 nums 中偶数下标 even 处的元素是否为偶数,若不是的话,遍历查找奇数下标 odd 处的元素,直到查到出现偶数,然后将 even 处和 odd 处元素交换即可
class Solution {
public:
vector<int> sortArrayByParityII(vector<int>& nums) {
int odd = 1;
for (int even = 0; even < nums.size(); even += 2)
{
if (nums[even] % 2 == 1)
{
while (nums[odd] % 2 == 1)
{
odd += 2;
}
swap(nums[even], nums[odd]);
}
}
return nums;
}
};