给定一个包含 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)是奇数还是偶数,注意完整的一圈指的是四边是否都有值
其余的事情就是分析清楚每一圈里每条边的起止点,并祝次加入ans列表中即可。
给定一个正整数 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为基数时,最终剩下最中间的一个数未填充。
给定一个链表,旋转链表,将链表每个节点向右移动 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