携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情
概述
数组算是一个并不复杂的数据结构,但就是这个,面试官就能在面试过程中考察出很多东西来。例如经典的排序问题,二分搜索,滑动窗口等等,都是在数组这种最基础等数据结构中处理问题的。
我们做数组类算法问题的时候,常常需要定义一个变量,明确该变量的意义,并不停的维护这个变量,也需要特别注意初始值
和边界
问题。
题目
给定一个包含红色、白色和蓝色、共 n
个元素的数组 nums
,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0
、 1
和 2
分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。
示例
输入: nums = [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
输入: nums = [2,0,1]
输出: [0,1,2]
提示
n == nums.length
1 <= n <= 300
nums[i]
为0
、1
或2
进阶
- 你可以不使用代码库中的排序函数来解决这道题吗?
- 你能想出一个仅使用常数空间的一趟扫描算法吗?
代码实现
要将数组中的3中元素进行排序,我们可以定义3个指针,分别划分3个元素的区域,中间部位的指针用来进行遍历操作,头尾两个部分的指针则用于做边界的划分以及元素的交换。
当遍历到当前的元素为 0
时,则需将其移动到数组的头部,同时右移0
的边界,反之依然,当遍历到当前的元素为2
时,则需将其移动到数组的尾部,同时左移2
的边界。
class Solution {
public void sortColors(int[] nums) {
// 边界处理
int len = nums.length;
if (len < 2) {
return;
}
// 0,1,2三个区间指针
int zero = 0, one = 0, two = len - 1;
// 当 1 和 2 相遇,则表示已经遍历完所有元素,终止循环
while (one <= two) {
// 移动数字 1 的指针,如果当前位置元素为 0,则将其交换至前面数字 0 的区域
if (nums[one] == 0) {
swap(nums, one, zero);
zero++;
one++;
} else if (nums[one] == 1) {
// 当前元素为 1,则继续往后遍历比较
one++;
} else {
// 当前元素为 2,则将其移动至数组尾部,并将数字 2 的区间缩小
swap(nums, one, two);
two--;
}
}
}
private void swap(int[] nums, int i, int j) {
// 交换两个元素的位置
nums[i] = nums[i] + nums[j] - (nums[j] = nums[i]);
}
}