[LeetCode交错正负数] | 刷题打卡
一直有刷题习惯,最近才看到掘金举办了刷题活动,特来参加!此题为第11题。不得不说掘金的主题就是漂亮呀!赞。
本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述:
描述 给出一个含有正整数和负整数的数组,重新排列成一个正负数交错的数组。
不需要保持正整数或者负整数原来的顺序。
样例 样例 1
输入 : [-1, -2, -3, 4, 5, 6]
输出 : [-1, 5, -2, 4, -3, 6]
解释 : 或者任何满足条件的答案
挑战
完成题目,且不消耗额外的空间。
二、思路分析:
划分不可避免循环两次,所以时间复杂度是
方法 | 描述 | 时间复杂度 | 空间复杂度 |
---|---|---|---|
双指针法 | 划分法,根据正负分类 | ||
双指针法 | 数量多的一类移动到后半部分 | ||
双指针法 | 指针分别+=2 、-=2 |
三、AC 代码:
import java.util.Arrays;
public class SolutionI {
public static void main(String[] args) {
int[] nums = new int[] { -1, -2, -3, 4, 5, 6 };
System.out.print(Arrays.toString(nums));
rerange(nums);
System.out.print(Arrays.toString(nums));
}
public static void rerange(int[] nums) {
// count positive and negative
int pos = 0;
int neg = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
pos++;
} else {
neg++;
}
}
// why need partition
partition(nums, pos > neg);
// why need interleave
interleave(nums, pos == neg);
}
/**
*
* @param nums
* @param hasSameLength
*/
private static void interleave(int[] nums, boolean hasSameLength) {
int left = 1;
int right = nums.length - 1;
// why need compare lenght
if (hasSameLength) {
right = nums.length - 2;
}
while (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
// rerange and space onte element
left += 2;
right -= 2;
}
}
private static void partition(int[] nums, boolean startPositive) {
// why need pivot
int pivot = startPositive ? 1 : -1;
int left = 0;
int right = nums.length - 1;
while (left <= right) {
while (left <= right && nums[left] * pivot > 0) {
left++;
}
while (left <= right && nums[right] * pivot < 0) {
right--;
}
if (left <= right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
}
}
四、总结:
题目收获:
- 此题虽然可以归类为双指针即相向双指针类问题
- 也可以归为划分算法类问题,因为要使用一次partition算法,将
正数
和负数
数量多的一方移动到后半部分 - 严格意义上来说,也属于计数类问题,因为在划分之前,要统计
正数
、负数
的数量,比较谁的数量多 - 直观上看它属于双指针的变种,即前面11道题目,
left
和right
变化量都为1
,此次变化量为+2
,以此类推,双指针的变化量并不是固定的.