【问题标题】:Why do slicing and sorted fail to reverse list in place?为什么切片和排序无法将列表反转到位?
【发布时间】:2019-12-04 00:40:06
【问题描述】:

我在 LeetCodeN(https://leetcode.com/problems/next-permutation/) 上做 NextPermutation 问题。问题需要我就地排序。这就是问题所在(来源:LeetCode):

“实现下一个排列,将数字重新排列为按字典顺序排列的下一个更大的数字排列。

如果这样的排列是不可能的,它必须将其重新排列为尽可能低的顺序(即按升序排序)。

替换必须就地进行并且仅使用恒定的额外内存。

这里有一些例子。输入在左列,其对应的输出在右列。

1,2,3 → 1,3,2 3,2,1 → 1,2,3 1,1,5 → 1,5,1 "[结束]

尝试了 nums = nums[::-1] 和 nums = sorted(nums) 并且都失败了测试用例 nums = [3,2,1] 因为数组似乎是未排序的。在这些分配之后我还打印了 nums,stdout 是 [1,2,3],这是正确的。这个错误没有意义,因为最后一行代码 nums[inverse_pt+1:] = sorted(nums[inverse_pt+1:]) 按预期修改了我的列表。最后,我尝试了 nums.sort(),它就地排序,结果成功了。

我已经阅读了reverse listslicing 上的帖子。

def nextPermutation(self, nums: List[int]) -> None:
    """
    Do not return anything, modify nums in-place instead.
    """
    if not nums or len(nums) == 1:
        return 
    # find inverse pt
    # O(1) because only 1 variable declared
    inverse_pt = len(nums) - 2
    while inverse_pt >= 0 and nums[inverse_pt+1] <= nums[inverse_pt]:
        inverse_pt -= 1

    if inverse_pt < 0:
        nums = sorted(nums)
        print(nums) # [1,2,3]
        return

    # find a smallest elem that's bigger than inverse_pt
    for i in range(len(nums)-1, inverse_pt, -1):
        if nums[i] > nums[inverse_pt]:
            nums[i], nums[inverse_pt] = nums[inverse_pt], nums[i]
            break

    # sort what's after new elem at inverse_pt
    nums[inverse_pt+1:] = sorted(nums[inverse_pt+1:])

【问题讨论】:

  • 请把 LeetCode 的问题直接放到你的帖子里。
  • 试试nums[:] = sorted(nums)
  • 我们无法说明您的直接尝试失败的原因,因为您没有描述您如何使用反转和排序尝试。
  • 就地通常意味着不需要额外的内存,而不仅仅是结果会覆盖原始输入。在这里,sorted 必须返回一个全新的列表,然后才能将其元素复制回现有列表 nums
  • 谢谢大家! @Stef,您的回答让我明白: nums 是对列表的引用,而不是列表本身,这就是 nums = sorted(nums) 实际上没有就地修改的原因。

标签: python


【解决方案1】:

它们没有就地排序,因为它们不是这样设计的。

切片总是会创建一个新列表,其中包含以某种顺序从原始列表中提取的元素子集。

sorted() 方法不对列表进行排序,它返回列表的排序版本

sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.
           ^^^^^^^^^^

reversed() 方法相同。

如果您想对列表进行就地排序,只需执行lst.sort():

sort(self, /, *, key=None, reverse=False)
    Stable sort *IN PLACE*.

一般来说,这是 python 设计理念的一部分。一般来说,一个方法将要么改变它的对象返回一个新的、改变版本的对象而不改变它。有几个值得注意的例外,主要是list.pop()(这对于数据科学的原因很重要,可以被认为是两个顺序操作的简写),但是切片和sorted()(和reversed())遵循这种范式。

【讨论】:

    猜你喜欢
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 2016-03-09
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多