leetcode 1260. Shift 2D Grid 详解 python3

一.问题描述

Given a 2D grid of size n * m and an integer k. You need to shift the grid k times.

In one shift operation:

  • Element at grid[i][j] becomes at grid[i][j + 1].
  • Element at grid[i][m - 1] becomes at grid[i + 1][0].
  • Element at grid[n - 1][m - 1] becomes at grid[0][0].

Return the 2D grid after applying shift operation k times.

Example 1:

Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
Output: [[9,1,2],[3,4,5],[6,7,8]]

Example 2:

Input: grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
Output: [[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]

Example 3:

Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
Output: [[1,2,3],[4,5,6],[7,8,9]]

Constraints:

  • 1 <= grid.length <= 50
  • 1 <= grid[i].length <= 50
  • -1000 <= grid[i][j] <= 1000
  • 0 <= k <= 100

二.解题思路

这道题方法有很多。

1.你可以定义一个单次shift函数然后执行k次shift函数即可。

每次shift函数就是将最后一列移到第一列,然后移动到第一列的最后一列的元素像下移。

因为python原生二维数组没有高级索引,所以只能迭代。

时间复杂度O(kmn)

如果用numpy倒是会简单一点,但是时间复杂度还是那样。

2.可以直接考虑到最后一步,执行了k次shift的数组会成什么样呢

<1 执行k次shift之后哪一列对应哪一列,这好找。

第j列对应j-k%m列,比如你向右移了一次,那么你现在的第二行就是移动前的第一行。

因为python数组支持负索引,比如a[-1]=a[len(a)-1],你可以直接写 res[i][j]=res[i][j-k%m]

因为你想如果只移动一次,那么第一列对应移动前最后一列,正常其他语言你应该写res[i][j]=res[i][m+j-k%m] if j-k%m<0,但是python的话不用。

<2 麻烦一点的就是行的确定,也就是res[i][j]=res[?][j-k%m]中的这个问号。

分析一下知:假如移动了k次,那么所有列至少向下移动了int(k/m)次,比如说数字列数为5,移动5次,相当于所有列都向下移动了一格。

之后要考虑,如果k不能整除m,相当于有些列它的向下移动次数是int(k/m)+1,比如说总共5列,移动6次,当移动5次的时候,相当于原数组全部向下移动一行,最后一行补到第一行,再这种情况下再移动一次,此时最后一列要再向下移动一次。

如果确定这些列?其实就是j-k%m<0的这些需要多移动一次,因为你想这些列的原对应列是不是 是从数组的后面拉到前面来的,而从后面拉倒前面来的全部都要下移。而那些不是从最后一列补过来的只要正常移动就好了。

综上所述,

 res[i][j]=grid[i-(int(k/m)+(j-k%m<0))%n][j-k%m]

记得行下移的时候记得%n

3.好像看到有人用了内置的chain函数,之后瞅一眼有时间补上。

PS:如果用numpy的话,高级索引会让这道题变得十分简单,但是本来咱们练leetcode不就是为了打基础吗?

更多leetcode算法题解法: 专栏 leetcode算法从零到结束

三.源码

两个版本,一个容易理解,另一个用列表解析(快一点)

# version 1
class Solution:
    def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:
        n,m=len(grid),len(grid[0])
        res=[[0]*m for j in range(n)]
        for j in range(m):
            for i in range(n):
                res[i][j]=grid[i-(int(k/m)+(j-k%m<0))%n][j-k%m]
        return res

#version 2
class Solution:
    def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:
        n,m=len(grid),len(grid[0])
        res=[grid[i-(int(k/m)+(j-k%m<0))%n][j-k%m] for i in range(n) for j in range(m)]
        return [res[i*m:(i+1)*m] for i in range(n)]
发布了218 篇原创文章 · 获赞 191 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/CSerwangjun/article/details/103175446