一枚菜鸟的leetcode刷题笔记 - Day7

54 - 螺旋矩阵

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        m, n = len(matrix), len(matrix[0])
        num = min((m+1)//2, (n+1)//2)
        ans = []
        if min(m,n) % 2 == 0:
            for i in range(0, num):
                for j1 in range(i, n-i-1):
                    ans.append(matrix[i][j1])
                for k1 in range(i, m-i-1):
                    ans.append(matrix[k1][n-1-i])
                for j2 in range(n-1-i, i, -1):
                    ans.append(matrix[m-1-i][j2])
                for k2 in range(m-1-i, i, -1):
                    ans.append(matrix[k2][i])
        else:
            for i in range(0, num-1):
                for j1 in range(i, n-i-1):
                    ans.append(matrix[i][j1])
                for k1 in range(i, m-i-1):
                    ans.append(matrix[k1][n-1-i])
                for j2 in range(n-1-i, i, -1):
                    ans.append(matrix[m-1-i][j2])
                for k2 in range(m-1-i, i, -1):
                    ans.append(matrix[k2][i])
            if m <= n:
                for i in range(num-1, n-num+1):
                    ans.append(matrix[num-1][i])
            else:
                for i in range(num-1, m-num+1):
                    ans.append(matrix[i][num-1])
        return ans

这个代码有点啰嗦了,估计还能精简。这个解法重要的是搞明白各种情况。

m和n分别表示矩阵的行数和列数,num用来表示转了几圈,最后一圈可以不完整,观察发现,最后一圈是否完整取决于min(m,n)是奇数还是偶数,注意完整的一圈指的是四边是否都有值

  1. 若是奇数,那么最后转不了完整的一圈,则要把最后一圈单独拿出来讨论;
  2. 若是偶数,那么最后一圈也是完整的,无需单独讨论;

其余的事情就是分析清楚每一圈里每条边的起止点,并祝次加入ans列表中即可。

59 - 螺旋矩阵 II

给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        ans = [[0 for _ in range(n)] for _ in range(n)]
        #写成ans = [[0] * n] * n也行
        num = (n+1)//2
        val = 0
        if n%2 == 0:
            for i in range(num):
                for j1 in range(i, n-i-1):
                    val += 1 
                    ans[i][j1] = val
                for k1 in range(i, n-i-1):
                    val += 1
                    ans[k1][n-1-i] = val
                for j2 in range(n-1-i, i, -1):
                    val += 1
                    ans[n-1-i][j2] = val
                for k2 in range(n-1-i, i, -1):
                    val += 1
                    ans[k2][i] = val
        else:
            for i in range(0, num-1):
                for j1 in range(i, n-i-1):
                    val += 1 
                    ans[i][j1] = val
                for k1 in range(i, n-i-1):
                    val += 1
                    ans[k1][n-1-i] = val
                for j2 in range(n-1-i, i, -1):
                    val += 1
                    ans[n-1-i][j2] = val
                for k2 in range(n-1-i, i, -1):
                    val += 1
                    ans[k2][i] = val
            ans[num-1][num-1] = val + 1
        return ans

和 54-螺旋矩阵 一样的思路,这题还简单些,因为矩阵的 row 和 col 都是 n.
num维护的是转的圈数,val维护的是要填入的值,每走一步使其+1.
还是分成n为奇数或偶数两种情况,当n为基数时,最终剩下最中间的一个数未填充。

61 - 旋转链表

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

示例 1:
输入: 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

示例 2:
输入: 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

一个超时的版本:

class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head:
            return head
        
        h1 = head
        h2 = head
        for i in range(0, k):   #写成range(0, k)而不是range(k)是为了防止k=0的情况
            if h1.next == None:
                h1 = head
            else:
                h1 = h1.next
        if h1 == h2:
            return head
        else:
            while h1.next:
                h1, h2 = h1.next, h2.next
            ansHead = h2.next
            h2.next = None
            h1.next = head
            return ansHead

这个解法超时了,超时的用例是:[1,2,3], 2000000000. 因为一直在陷在 for 循环里。这题要想通过肯定不能一直next

之前没有考虑到 k 可能很大的情况,于是写了个 for 循环导致超时,下面的版本为了避免这一点,先遍历了一遍链表,找到链表中节点的总个数 num,并令 k=k%num,再按照之前的双指针的思路就通过了。

class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head:
            return head
        #这一段是为了找到num
        num = 1
        h3 = head
        while h3.next:
            h3 = h3.next
            num += 1
        k = k % num
        #考虑k=0的情况
        if k == 0:
            return head
        #开始双指针法,先让h1和h2拉开k步
        h1 = head
        h2 = head
        for i in range(0, k):   #写成range(0, k)而不是range(k)是为了防止k=0的情况
                h1 = h1.next
        #让h1和h2一起走,直到h1走到链表的最后一个节点,即 h1.next = None
        while h1.next:
            h1, h2 = h1.next, h2.next
        ansHead = h2.next
        h2.next = None
        h1.next = head
        return ansHead
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值