- 初始解法
最开始的想法是用三个指针来解决该问题,分别是left, right和tmp。其中
也就是left和right代表着最长0串或2串的边界。tmp指针指向当前正在处理的位置。
而出于对于特殊情况的考虑,先判断nums是否为空,若为空,则直接返回。
接下来为了达到(1)(2)式的要求,先用循环将left和right的初始位置设置好。
while left < right and nums[left] == 0:
left += 1
while left < right and nums[right] == 2:
right -= 1
此时就可以开始处理left和right之间的数组。处理方式就是用tmp指针扫一遍数组,将扫到的0放到左边,扫到的2放到右边。具体的处理方式是,如果扫到0,那么就将nums[left]与nums[tmp]替换,同时将left指针右移一格;如果扫到2,那么就考察nums[right]的值,如果值为0,那么就可以在更新nums[right]的值的同时更新nums[left]的值,将left和right的值同时移动,如果值不为0,那么就将nums[left]与nums[tmp]替换,right左移一格。此处需要注意,由于left在tmp左边,所以nums[left]只有可能是1,所以扫到0的时候不用考察nums[left]的值就可以直接替换。
在进行如上更新后,可能此时的nums[left]为0,nums[right]为2,所以又要进行left和right的更新,使得此时的left和right达到(1)(2)式的要求。而tmp也要根据left进行更新,如果left更新后到了tmp的右边,那么就将tmp更新为此时的left。
tmp指针扫完left和right之间的数组,也就是tmp>right的时候,整个算法就已经完成了。就地排序完成。
总体代码如下:
class Solution:
def sortColors(self, nums: List[int]) -> None:
# empty list
if not nums:
return
l = len(nums)
right = l-1
left = 0
while left < right and nums[left] == 0:
left += 1
while left < right and nums[right] == 2:
right -= 1
tmp = left
while tmp <= right:
if nums[tmp] == 2:
if nums[right] == 0:
nums[tmp] = nums[left]
nums[left] = 0
nums[right] = 2
left += 1
right -= 1
else:
nums[tmp] = nums[right]
nums[right] = 2
right -= 1
else:
if nums[tmp] == 0:
nums[tmp] = nums[left]
nums[left] = 0
left += 1
while left < right and nums[left] == 0:
left += 1
while left < right and nums[right] == 2:
right -= 1
tmp = max(tmp+1, left)
return
- 官方解法
在看到官方解法后,觉得自己的方法虽然时间复杂度和空间复杂度并没有特别大的劣势,但是代码不够简洁,思路不够清晰,所以又参考了官方代码改了一版答案。
官方代码的思路是也是用三个指针,分别是left、right和tmp,但是left、right需要满足的条件和我的代码的条件不同。
官方解法对nums[left]和nums[right]没有要求,所以就不用写那两个循环。
思路依然是将0全都移到left指针左边,2移到right指针右边。将数组从头到尾扫一遍,如果nums[tmp]为0,就将nums[left]与nums[tmp]替换,将0移到left左边,同时将left和tmp均向右移一格,如果nums[tmp]为1,那么就直接将tmp向右移一格,如果nums[tmp]为2,就将nums[right]与nums[tmp]替换,同时将right向左移一格,将2移到right右边,因为nums[right]的值没有被考察过,所以此时tmp不能向右移。
完整代码:
class Solution:
def sortColors(self, nums: List[int]) -> None:
# empty list
if not nums:
return
l = len(nums)
right = l-1
left = 0
tmp = left
while tmp <= right:
if nums[tmp] == 0:
nums[tmp] = nums[left]
nums[left] = 0
tmp += 1
left += 1
elif nums[tmp] == 2:
nums[tmp] = nums[right]
nums[right] = 2
right -= 1
else:
tmp += 1
return