TLP-Task07学习笔记


本篇为Datawhale组队学习计划第21期LeetCode精选题目组Task07学习笔记。
初学,时间有点仓促,很多解法没有详细分析,未来可能会修改,见谅。
Datawhale学习文档:
https://github.com/datawhalechina/team-learning-program/tree/master/LeetCodeTencent

054 螺旋矩阵

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/spiral-matrix

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例:

输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

思路

(好像又是眼熟的题目)
基本思路是模拟行走过程,改变坐标x,y,改变边界值,判断边界交错情况(下一步是否合理)。

可以模拟螺旋矩阵的路径。初始位置是矩阵的左上角,初始方向是向右,当路径超出界限或者进入之前访问过的位置时,则顺时针旋转,进入下一个方向。
判断路径是否进入之前访问过的位置需要使用一个与输入矩阵大小相同的辅助矩阵visited,其中的每个元素表示该位置是否被访问过。当一个元素被访问时,将visited中的对应位置的元素设为已访问。
如何判断路径是否结束?由于矩阵中的每个元素都被访问一次,因此路径的长度即为矩阵中的元素数量,当路径的长度达到矩阵中的元素数量时即为完整路径,将该路径返回。

这里结合其他的思路,不使用辅助矩阵,而是将访问过的元素直接修改为‘v’。相对比较好理解,空间复杂度稍好一点。
参考
https://leetcode-cn.com/problems/spiral-matrix/solution/luo-xuan-ju-zhen-by-leetcode-solution/
https://leetcode-cn.com/problems/spiral-matrix/solution/cxiang-xi-ti-jie-by-youlookdeliciousc-3/
https://blog.csdn.net/qq_36512295/article/details/100669301

Python实现

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix:
            return list()
        m,n = len(matrix), len(matrix[0])
        total = m * n
        # 顺时针方向(右下左上),dm,dn分别用于改变x,y坐标
        dm = [0, 1, 0, -1]       
        dn = [1, 0, -1, 0]
        di = 0                   # 方向指针
        res = []
        x = y = 0                # 位置
        for i in range(total):     # 最多步长 m*ii
            res.append(matrix[x][y])
            matrix[x][y] = 'v'   # 便于后面判断,将访问过的标记为 'v'
            # 下一步位置
            x_temp = x + dm[di] 
            y_temp = y + dn[di]
            # 判断下一步位置是否合理,若合理则更新位置,若不合理则改变方向并更新位置
            if 0<=x_temp<m and 0<=y_temp<n and matrix[x_temp][y_temp]!='v':
                x, y = x_temp, y_temp
            else:
                di = (di+1) % 4 # 继续走,改变坐标
                x += dm[di]
                y += dn[di]
        return res
        

059 螺旋矩阵Ⅱ

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/spiral-matrix-ii

扫描二维码关注公众号,回复: 12277595 查看本文章

给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

示例:

输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]

思路

思路与刚才相似,只是将读取换为写入,方阵也降低了难度。

生成一个 n×n 空矩阵 mat,随后模拟整个向内环绕的填入过程:

定义当前左右上下边界 l,r,t,b,初始值 num = 1,迭代终止值 tar = n * n;
当 num <= tar 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后:
执行 num += 1:得到下一个需要填入的数字;
更新边界:例如从左到右填完后,上边界 t += 1,相当于上边界向内缩 1。
使用num <= tar而不是l < r || t < b作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。

参考:https://leetcode-cn.com/problems/spiral-matrix-ii/solution/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/

Python实现

代码主要参考上述题解,有所修改。

class Solution:
    def generateMatrix(self, n: int) -> [[int]]:
        l, r, t, b = 0, n - 1, 0, n - 1   # n为正整数
        mat = [[0]*n for i in range(n)]   # 初始化矩阵mat
        num = 1
        tar = n * n
        while num <= tar:
            for i in range(l, r + 1): # left to right
                mat[t][i] = num
                num += 1
            t += 1
            for i in range(t, b + 1): # top to bottom
                mat[i][r] = num
                num += 1
            r -= 1
            for i in range(r, l - 1, -1): # right to left
                mat[b][i] = num
                num += 1
            b -= 1
            for i in range(b, t - 1, -1): # bottom to top
                mat[i][l] = num
                num += 1
            l += 1
        return mat
        

061 旋转链表

思路

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotate-list

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

示例:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL

思路

1.k>链表长度n时,k=k%n
2.链表先成环,再在对应位置断开形成新的头尾,调整尾部指针。

图片来自官方题解

Python实现

class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head:
            return None
        if not head.next:
            return head
        old_tail = head 
        
		# 确定链表长度n
        n = 1
        while old_tail.next:    
            old_tail = old_tail.next
            n += 1
        old_tail.next = head	# 重要 
        
        #new tail : (n - k % n - 1)th node
        #new head : (n - k % n)th node
        new_tail = head
        for i in range(n - k % n - 1):
            new_tail = new_tail.next
        new_head = new_tail.next

        new_tail.next = None
        return new_head
        

猜你喜欢

转载自blog.csdn.net/cosima0/article/details/112797616