Medium
题目描述
给你一个下标从 0 开始的整数数组 nums,数组长度为 偶数,由数量相等的正整数和负整数组成。
你需要重排 nums 中的元素,使数组满足下述条件:
- 任意 连续 的两个整数符号 相反
- 对于符号相同的所有整数,保留 它们在
nums中的 顺序 - 重排后的数组以 正整数 开头
请你返回满足上述条件的重排数组。
示例 1:
输入:nums = [3,1,-2,-5,2,-4]
输出:[3,-2,1,-5,2,-4]
解释:
nums 中的正整数是 [3,1,2],负整数是 [-2,-5,-4]。
重排的唯一可能方案是 [3,-2,1,-5,2,-4],能满足所有条件。
其他方案如 [1,-2,2,-5,3,-4]、[3,1,2,-2,-5,-4]、[-2,3,-5,1,-4,2] 都不满足至少一个条件。
示例 2:
输入:nums = [-1,1]
输出:[1,-1]
解释:
1 是 nums 中唯一的正整数,-1 是 nums 中唯一的负整数。
所以 nums 重排为 [1,-1]。
提示:
2 <= nums.length <= 2 * 10^5nums.length是 偶数1 <= |nums[i]| <= 10^5nums由相等数量的正整数和负整数组成
进阶: 可以不使用额外空间并在原数组上操作吗?
解题思路
这道题要求我们重新排列数组,使得正负数交替出现,且保持相同符号数字的相对顺序。
解法一:双指针直接填充(推荐)
最直观的思路是利用题目给出的规律:最终数组的偶数位置(0,2,4…)应该放正数,奇数位置(1,3,5…)应该放负数。
我们可以遍历原数组,用两个指针分别指向结果数组中应该放正数和负数的位置:
pos = 0:指向下一个应该放正数的位置(偶数索引)neg = 1:指向下一个应该放负数的位置(奇数索引)
遇到正数就放到 pos 位置并让 pos += 2,遇到负数就放到 neg 位置并让 neg += 2。
这种方法时间复杂度为 O(n),空间复杂度为 O(1)(不包括结果数组)。
解法二:分离再合并
先将正数和负数分别提取出来,然后交替合并。这种方法需要额外的空间来存储正数和负数数组,空间复杂度稍高。
第一种解法更优,因为它直接在结果数组上操作,避免了额外的存储开销。
代码实现
class Solution {
public:
vector<int> rearrangeArray(vector<int>& nums) {
int n = nums.size();
vector<int> result(n);
int pos = 0, neg = 1; // pos指向偶数位置,neg指向奇数位置
for (int num : nums) {
if (num > 0) {
result[pos] = num;
pos += 2;
} else {
result[neg] = num;
neg += 2;
}
}
return result;
}
};
class Solution:
def rearrangeArray(self, nums: List[int]) -> List[int]:
n = len(nums)
result = [0] * n
pos, neg = 0, 1 # pos指向偶数位置,neg指向奇数位置
for num in nums:
if num > 0:
result[pos] = num
pos += 2
else:
result[neg] = num
neg += 2
return result
public class Solution {
public int[] RearrangeArray(int[] nums) {
int n = nums.Length;
int[] result = new int[n];
int pos = 0, neg = 1; // pos指向偶数位置,neg指向奇数位置
foreach (int num in nums) {
if (num > 0) {
result[pos] = num;
pos += 2;
} else {
result[neg] = num;
neg += 2;
}
}
return result;
}
}
/**
* @param {number[]} nums
* @return {number[]}
*/
var rearrangeArray = function(nums) {
const n = nums.length;
const result = new Array(n);
let pos = 0, neg = 1; // pos指向偶数位置,neg指向奇数位置
for (const num of nums) {
if (num > 0) {
result[pos] = num;
pos += 2;
} else {
result[neg] = num;
neg += 2;
}
}
return result;
};
复杂度分析
| 复杂度类型 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 只需要遍历一次原数组 |
| 空间复杂度 | O(1) | 除了结果数组外,只使用了常数个额外变量 |