使用区间来简化代码思考

  Leetcode中移动零(https://leetcode-cn.com/problems/move-zeroes/)和快速排序的最初版本,本质上都可以使用区间来简化代码。

  首先以移动零为例,假设两个循环变量分别为 j j j i i i(假设 j < = i j<=i j<=i),则 [ 0 , . . . , j ] [0,...,j] [0,...,j]中均为非零元素(区间1),而 [ j + 1 , . . . , i − 1 ] [j+1,...,i-1] [j+1,...,i1]均为零(区间2)。其中i是从最开始滑到最后一个元素的。
在这里插入图片描述
  由于区间1和区间2最开始都没有元素,则两个区间应该为空,所以得到 j = − 1 j=-1 j=1以及 i = 0 i=0 i=0。假设nums[i]为0,则什么都不要做,假设nums[i]不为0,则需要进行交换。具体如代码:

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # [0, j] not zero, [j+1, i-1] all zero
        j = -1
        for i in range(0, len(nums)):
            if nums[i] != 0:
                nums[i], nums[j+1] = nums[j+1], nums[i]
                j += 1

  接着以最简单的快速排序中partition函数为例。
在这里插入图片描述

def partition(nums, l, r):
    # [l+1,...,j] < v, [j+1,...,i-1] > v
    v = nums[l]
    j = l

    for i in range(l+1, r+1):
        if nums[i] < v:
            nums[i], nums[j+1] =  nums[j+1], nums[i]
            j += 1

    nums[l], nums[j] = nums[j], nums[l]

    return j

  如果是两个区间,则 j j j从-1开始,如果是单个区间,则 j j j从0或者其他正整数开始。(更准确的解释是说,如果已经有基准元素的话, j j j从-1开始,如果需要基准元素,则需要向前走N步,得到基准元素,则 j j j从0或者其他正整数开始)。

  1. 删除排序数组中的重复项
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # [0,...j] non duplicates i
        j = 0

        for i in range(0, len(nums)):
            if nums[j] != nums[i]:
                nums[j+1] = nums[i]
                j += 1

        return j + 1
  1. 移除元素
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        #[0,...j] != val, [j+1,...i-1] == val

        j = -1
        for i in range(0, len(nums)):
            if nums[i] != val:
                nums[i], nums[j+1] = nums[j+1], nums[i]
                j += 1

        return j + 1
  1. 删除排序数组中的重复项
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # [0,...j] non duplicates i
		if len(nums) == 0:
			return 0
			
        j = 0

        for i in range(0, len(nums)):
            if nums[j] != nums[i]:
                nums[j+1] = nums[i]
                j += 1

        return j + 1
  1. 删除排序数组中的重复项 II
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # [0,...j] non duplicates
		if len(nums) <=1:
			return len(nums)

        j = 1

        for i in range(2, len(nums)):
            if not (nums[i] == nums[j] and nums[i] == nums[j-1]):
                nums[j+1] = nums[i]
                j += 1

        return j + 1
class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # [0, zeros] 0, [zeros+1, i-1] 1, [two, n-1] 2
        zeros = -1
        i = 0
        two = len(nums)

        while i < two:
            if nums[i] == 0:
                nums[zeros+1], nums[i] = nums[i], nums[zeros+1]
                zeros += 1
                i += 1
            elif nums[i] == 1:
                i += 1
            else:
                nums[two-1], nums[i] = nums[i], nums[two-1]
                two -= 1

多个区间的问题怎么解决呢?
https://bohenan.gitbooks.io/leetcode/lai-rainbow-sort-iii.html
http://sgq626.blogspot.com/2015/07/leetcode-75-sort-colors-sort-color-ii.html

猜你喜欢

转载自blog.csdn.net/herosunly/article/details/107160711