I am trying to solve the LeetCode problem 189. Rotate Array in Python:
Given an array, rotate the array to the right by k steps, where k is non-negative.
class Solution: def rotate(self, nums: List[int], k: int) -> None: """ Do not return anything, modify nums in-place instead. """
The following code works:
n = len(nums)
k = k % n
nums[k:], nums[:k] = nums[:-k], nums[-k:]
But if I change the order of the assignments in the last line, i.e. replace it with
nums[:k], nums[k:] = nums[-k:], nums[:-k]
the code doesn't work for the case of k=0. Clearly in this case, nums[:k] and nums[:-k] would be empty and the sizes of the lists on the left hand side and the right hand side don't match, but somehow the first code works and the second one doesn't.
Can someone explain?
CodePudding user response:
The order in which the tuple assignment is executed, is indeed relevant here.
Let's say nums is [1,2,3,4] (and k 0)
Then the non-working assignment comes down to this:
nums[:0], nums[0:] = [1,2,3,4], []
...which is executed in this order:
nums[:0] = [1,2,3,4]
nums[0:] = []
It is now clear that the latter assignment destroys the effect of the first. It is also clear if they were executed in the opposite order, the end result would be fine.
So the order of assignments matter, even in tuple assignments.
The deeper reason why the behaviour is different specifically when k is 0, is related to how -k works in a slice notation: this always counts abs(k) steps backwards from the end, except when k=0: then it represents the very first index.
You would not have this different behaviour if you would do this:
nums[:k], nums[k:] = nums[len(nums)-k:], nums[:len(nums)-k]
Now it is explicit that the index should be determined by stepping backwards from the end, even when k is 0. This tuple assignment can be swapped, and it will still work, also for k equal to 0.
CodePudding user response:
Well, consider this:
nums = [1, 2, 3]
nums[:0], nums[0:] = [1, 2, 3], []
print(nums)
Given the next to last line, what would you expect nums to be? The problem is that the statement is ambiguous to begin with and it just happens to be that the second implementation gets you an undesirable result - it resets the entire list to [] after adding [1,2,3] to the start. The first implementation does it the other way around.
What you were really after:
nums = nums[k:] nums[:k]
CodePudding user response:
You can handle the case when k=0 as a base case. For k=0, you can return the actual list, and use @trincot's answer for any other value of k.
