Description
Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same
color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Example
Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
Follow up
1.A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
2.Could you come up with a one-pass algorithm using only constant space?
Solution 1(C++)
class Solution {
public:
void sortColors(vector<int>& nums) {
int len=nums.size();
for(int i=0; i<len; i++){
for(int j=i+1; j<len; j++){
if(nums[i]>nums[j]){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}
}
}
};
Solution 2(C++)
class Solution {
public:
void sortColors(vector<int>& nums) {
int left=0, right=nums.size()-1;
while(left<right){
for(int i=left; i<right; i++){
if(nums[i]>nums[i+1]){
int temp=nums[i];
nums[i]=nums[i+1];
nums[i+1]=temp;
}
}
right--;
for(int i=right; i>left; i--){
if(nums[i]<nums[i-1]){
int temp=nums[i];
nums[i]=nums[i-1];
nums[i-1]=temp;
}
}
left++;
}
}
};
Solution 3(C++)
class Solution {
public:
void sortColors(vector<int>& nums) {
int len=nums.size();
for(int i=0; i<len; i++){
int min=i;
for(int j=i+1; j<len; j++){
if(nums[j]<nums[min]){
min=j;
}
}
if(i!=min){
int temp=nums[i];
nums[i]=nums[min];
nums[min]=temp;
}
}
}
};
Solution 4(C++)
class Solution {
public:
void sortColors(vector<int>& nums) {
int len=nums.size();
for(int i=1, j; i<len; i++){
int get=nums[i];
for(j=i-1; j>=0 && nums[j]>get; j--){
nums[j+1]=nums[j];
}
nums[j+1]=get;
}
}
};
Solution 5(C++)
class Solution {
public:
void sortColors(vector<int>& nums) {
int len=nums.size();
for(int i=1; i<len; i++){
int get=nums[i];
int left=0, right=i-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]>get) right=mid-1;
else left=mid+1;
}
for(int j=i-1; j>=left; j--){
nums[j+1]=nums[j];
}
nums[left]=get;
}
}
};
Solution 6(C++)
class Solution {
public:
void sortColors(vector<int>& nums) {
int len=nums.size();
int h=0;
while(h<=len){
h = 3*h + 1;
}
while(h>=1){
for(int i=1; i<len; i++){
int get=nums[i], j;
for(j=i-h; j>=0 && nums[j]>get; j -= h){
nums[j+h]=nums[j];
}
nums[j+h]=get;
}
h=(h-1)/3;
}
}
};
Solution 7(C++)
class Solution {
public:
void Merge(vector<int>& nums, int left, int mid, int right){
int len=right-left+1;
vector<int> temp(len,0);
int index=0;
int i=left, j=mid+1;
while(i<=mid && j<=right){
temp[index++] = nums[i] <= nums[j] ? nums[i++]:nums[j++];
}
while(i<=mid){
temp[index++] = nums[i++];
}
while(j<=right){
temp[index++] = nums[j++];
}
for(int k=0; k<len; k++){
nums[left++] = temp[k];
}
}
void MergeSortRecursion(vector<int>& nums, int left, int right){
if(left==right) return;
int mid=left+(right-left)/2;
MergeSortRecursion(nums, left, mid);
MergeSortRecursion(nums, mid+1, right);
Merge(nums, left, mid, right);
}
void sortColors(vector<int>& nums) {
int len=nums.size();
MergeSortRecursion(nums, 0, len-1);
}
};
Solution 8(C++)
class Solution {
public:
void Merge(vector<int>& nums, int left, int mid, int right){
int len=right-left+1;
vector<int> temp(len,0);
int index=0;
int i=left, j=mid+1;
while(i<=mid && j<=right){
temp[index++] = nums[i] <= nums[j] ? nums[i++]:nums[j++];
}
while(i<=mid){
temp[index++] = nums[i++];
}
while(j<=right){
temp[index++] = nums[j++];
}
for(int k=0; k<len; k++){
nums[left++] = temp[k];
}
}
void MergeSortIteration(vector<int>& nums, int len){
int left, mid, right;
for (int i = 1; i < len; i *= 2) { // 子数组的大小i初始为1,每轮翻倍
left = 0;
while (left + i < len) { // 后一个子数组存在(需要归并)
mid = left + i - 1;
right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够
Merge(nums, left, mid, right);
left = right + 1; // 前一个子数组索引向后移动
}
}
}
void sortColors(vector<int>& nums) {
int len=nums.size();
MergeSortIteration(nums, len);
}
Solution 9(C++)
class Solution {
public:
void Swap(vector<int>& nums, int i, int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
void Heapify(vector<int>& nums, int i, int size){
int left_child = 2 * i + 1;
int right_child = 2 * i + 2;
int max=i;
if (left_child < size && nums[left_child] > nums[max])
max = left_child;
if (right_child < size && nums[right_child] > nums[max])
max = right_child;
if (max != i){
Swap(nums, i, max);
Heapify(nums, max, size);
}
}
int BuildHeap(vector<int>& nums, int n){
int heap_size = n;
for (int i = heap_size / 2 - 1; i >= 0; i--)
Heapify(nums, i, heap_size);
return heap_size;
}
void HeapSort(vector<int>& nums, int n){
int heap_size = BuildHeap(nums, n);
while(heap_size > 1){
Swap(nums, 0, --heap_size);
Heapify(nums, 0, heap_size);
}
}
void sortColors(vector<int>& nums) {
int len=nums.size();
HeapSort(nums, len);
}
};
Solution 10(C++)
class Solution {
public:
void Swap(vector<int>& nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
int Partition(vector<int>& nums, int left, int right){
int pivot = nums[right]; // 这里每次都选择最后一个元素作为基准
int tail = left - 1; // tail为小于基准的子数组最后一个元素的索引
for (int i = left; i < right; i++){
if (nums[i] <= pivot){
Swap(nums, ++tail, i);
}
}
Swap(nums, tail + 1, right); // 最后把基准放到前一个子数组的后边,剩下的子数组既是大于基准的子数组
// 该操作很有可能把后面元素的稳定性打乱,所以快速排序是不稳定的排序算法
return tail + 1; // 返回基准的索引
}
void QuickSort(vector<int>& nums, int left, int right){
if (left >= right)
return;
int pivot_index = Partition(nums, left, right); // 基准的索引
QuickSort(nums, left, pivot_index - 1);
QuickSort(nums, pivot_index + 1, right);
}
void sortColors(vector<int>& nums) {
QuickSort(nums, 0, nums.size()-1);
}
};
后续更新
其他相关题目可参考:
算法分析
我借用这一道题,把排序的主要算法都学习了一遍。主要参考:
常用排序算法总结(一)
这里介绍的都是比较排序,还有非比较排序可以参考:
常用排序算法总结(二)
这排序肯定要用单独的一篇博客来系统整理一下了。毕竟太经典也太重要了。
程序分析
这个一定要多动手写几遍。