题目一:
给定一个数组 arr,一个数 num,请把小于等于 num 的数放在数组的左边,大于 num 的数放在数组的右边。
要求额外空间复杂度 O(1),时间复杂度 O(N)
思路:
以 num 为界把数组分为两部分:
1. 左侧 <= num 区域
2. 右侧 >= num 区域
那么我们可以设定一个边界的 idx,当前元素与 num 进行比较:
1. 如果 [i] <= num,边界右侧的元素与 [i] 之间的元素是 > num 的元素,所以我们首先要将 [i] <> 边界右侧元素进行交换,然后把边界右扩
2. 如果 [i] > num,那么边界不动,直接判定下一个元素
图示:
1. 初始边界 less = -1,当前元素 = 3,小于 5,与 less+1 元素交换(3)
2. 交换完成边界右扩,同理交换,并且右扩
3. 元素 6, 7 不满足,直接跳过,到达元素 4 ,进行交换(4<>6)
4. 如此循环,知道 cur 遍历完整个数组
代码:
void sortbynum(int *arr, int len, int num)
{
int less = -1;
int i;
for(i=0; i<len; i++)
{
if(arr[i] <= num) // [i] <= num
{
swap(arr, i, less+1);
less++;
}
else // [i] > num
{
// just ignore
}
}
}
通过这种方式不断的将 小于边界右扩,把大于部分推向右侧
下一章节继续荷兰国旗问题的升级版本
再讲述完这两个部分后,我们会引入 快速排序,那个时候就清楚为什么要先了解荷兰国旗问题