问题描述:
给定一个数组,只能存放 0 1 2三个数字,给出一个算法,使得数组最终成00…11…22的形式,即0都集中在最前面,2集中在最后面。
问题分析与code:
- 排序,根据数据规模以及数据有序情况,选择一个排序算法;
- 计数的方法,分别统计0 1 2个数,然后根据个数赋值数组:
void Holland(int *arr,int len)
{
int count_0 = 0;
int count_1 = 0;
int count_2 = 0;
for(int i = 0;i<len;++i)
{
if(arr[i] == 0)
{
count_0++;
}
if(arr[i] == 1)
{
count_1++;
}
if (arr[i] == 2)
{
count_2++;
}
}
for(int i = 0;i<count_0;++i)
{
arr[i] = 0;
}
for(int i = count_0;i<count_0+count_1;++i)
{
arr[i] = 1;
}
for(int i = count_0+count_1;i<len;++i)
{
arr[i] = 2;
}
}
- 采用类似快排的划分的思想,三指针遍历,将0放在数组靠前,2放在靠后:
void Holland(int *arr,int len)
{
int begin = 0;
int end = len- 1;
int cur = 0;
int tmp = 0;
while(cur <= end)
{
if(arr[cur] == 2)
{
tmp = arr[cur];
arr[cur] = arr[end];
arr[end] = tmp;
cur++;
end--;
}
if(arr[cur] == 0)
{
if(cur == begin)
{
cur++;
}
else
{
tmp = arr[cur];
arr[cur] = arr[begin];
arr[begin] = tmp;
}
begin++;
}
if(arr[cur] == 1)
{
cur++;
}
}
}
引申:
乌克兰国旗问题:
- 奇数偶数,比如奇数在前,偶数在后
- 整数负数,比如正数在前,偶数在后