目录
题目
代码
//交换函数,交换指针a和指针b指向的整数
void swap(int *a, int *b){
int t = *a;
*a = *b;
*b = t;
}
void sortColors(int* nums, int numsSize) {
//双指针
int p0 = 0, p1 = 0;
//遍历数组
for(int i = 0; i < numsSize; ++i){
//把0丢给p0,此时如果p0<p1,也就是遇到过1,那p0指向的数必为1,需要把1丢给p1
//p0左边都是0,p1左边排列好的0和1,p0在p1左边,所以p0所指必定为1
if(0 == nums[i]){
swap(&nums[i], &nums[p0]);
if(p0 < p1){
swap(&nums[i], &nums[p1]);
}
++p0, ++p1;
}
//把1丢给p1,之后p1++
else if(1 == nums[i]){
swap(&nums[i], &nums[p1]);
++p1;
}
//指针总结
//p0是慢指针只有在遇到0才++,所以p0左边都是0
//p1是快指针,遇到0或1才++,所以p1左边都是0和1
}
}
分析
案例模拟
i = 0
i = 1
遇到了0,丢给p0,双指针++
i = 2
i = 3
遇到了1,丢给p1,p1++
i = 4
遇到1,丢给p1,p1++
i = 5
遇到0,丢给p0,
此时p0 < p1,sums( i )的值丢给p1后,再双指针++
重难点分析
这题最难理解的地方,在于遇到1,而且p0 < p1时,为什么要做这么麻烦的交换。也就是代码中的这部分:
对应于上面案例分析中 i = 5 的时候。
在这种解法中,p0是慢指针,只有在遇到0时才++,所以p0左边都是0;p1是快指针,遇到0或1时都会++,所以p1左边都是0和1,又因为p0已经把0都排好了,所以p1左边是按01排好的0和1。
相对位置如下:
所以,代码中p0 < p1 的含义在于,此时p0所指的一定是1,而1在与遇到的0交换后,还应该换到p1的脚下,这种情况下p0遇到的0的总数+1,p1遇到的0和1的总数也+1(有一对0和1内部交换),所以双指针++。
而代码中的交换过程也显得比较复杂,还是靠图来辅助理解:
可以看到,p0, p1和nums(i)他们相互交换了值,就像过节日三个好朋友互相交换礼物。
再由上面的分析,我们可以知道,交换前p0的值为1,nums(i)的值为0,把数值填入能得到下表:
可以看到,确实是实现了把0给p0,把1给p1的操作。
自检复习
如果你能完全分析出下面这个视频那就说明你真的有收获啦。
<iframe allowfullscreen="true" data-mediaembed="bilibili" frameborder="0" id="EtmIdpEa-1716469047257" src="https://player.bilibili.com/player.html?aid=1504924740"></iframe>每日一练——颜色分类(快慢指针排序)
标签:快慢,p0,p1,遇到,++,int,排序,指针 From: https://blog.csdn.net/weixin_73483158/article/details/139156333