目录
一、内容
问题一
给定一个数组arr,和一个num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)
问题二(荷兰国旗问题)
给定一个数组arr,和一个num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)
二、分析
问题一
定义一个小于等于区域(从数组最左侧开始,不包含第一个元素)
1) arr[i] <= num,arr[i]和小于等于区域的下一个数交换,小于等于区右扩,i++
2) arr[i] > num, i++
原理:右侧为待定区域,小于等于区域(已经满足条件),小于等于区域右侧到 i 的区域是大于区域。即随着 i 的遍历的过程中小于等于区域推着大于区域往右走,当小于等于区域把大于区域推到整个数组范围的时候,即可满足条件
问题二
问题二(荷兰国旗问题)即为问题一的升级版
定义一个小于区域(从数组最左侧开始,不包含第一个元素),再定义一个大于区域(从数组最右侧开始,不包含最后一个元素)
1) arr[i] < num,arr[i]和小于区域的下一个数交换,小于区右扩,i++
2) arr[i] == num, i++
3) arr[i] > num,arr[i]和大于区域的前一个数交换,大于区域左扩,i不变
原理:在问题一的基础上,增加了大于区域。随着i的遍历小于区域向右推进,大于区域向左推进,当 i 推进到大于区域的初始位置时,既满足条件
三、总结
整体思想是基于题目条件进行的区块划分,在 i 遍历的过程中将满足条件的元素归于自己的区块,以此达到条件
另外提一嘴:快排也可以采用这个思路哦(感兴趣的小伙伴们可以自己去尝试一下)