Leetcode Task07:完成54、59、61题目并打卡
054 螺旋矩阵
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
解法
给出⼀个⼆维数组,按照螺旋的⽅式输出
解法⼀:需要注意的是特殊情况,⽐如⼆维数组退化成⼀维或者⼀列或者⼀个元素。注意了这些情况,基本就可以⼀次通过了。
解法⼆:提前算出⼀共多少个元素,⼀圈⼀圈地遍历矩阵,停⽌条件就是遍历了所有元素(count == sum)
官方解法
绘制螺旋轨迹路径,我们发现当路径超出界限或者进入之前访问过的单元格时,会顺时针旋转方向。
假设数组有R 行 C 列,seen[r,c]表示第 r 行第 c 列的单元格之前已经被访问过了。当前所在位置为(r, c),前进方向是 di。我们希望访问所有R x C 个单元格。
当我们遍历整个矩阵,下一步候选移动位置是(cr, cc)。如果这个候选位置在矩阵范围内并且没有被访问过,那么它将会变成下一步移动的位置;否则,我们将前进方向顺时针旋转之后再计算下一步的移动位置。
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list = new ArrayList<>();
if(matrix.length==0){
return list;
}
int rowlen = matrix.length;
int collen = matrix[0].length;
int total_num = 0;
int left = 0;
int right = collen - 1;
int top = 0;
int bottom = rowlen - 1;
while (total_num != rowlen * collen) {
for (int i = left; i <= right; i++) {
list.add(matrix[top][i]);
total_num++;
}
if (total_num == rowlen * collen) break;
top++;
for (int i = top; i <= bottom; i++) {
list.add(matrix[i][right]);
total_num++;
}
if (total_num == rowlen * collen) break;
right--;
for (int i = right; i >= left; i--) {
list.add(matrix[bottom][i]);
total_num++;
}
if (total_num == rowlen * collen) break;
bottom--;
for (int i = bottom; i >= top; i--) {
list.add(matrix[i][left]);
total_num++;
}
if (total_num == rowlen * collen) break;
left++;
}
return list;
}
}
059 螺旋矩阵 II
Given a positive integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.
给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
解题思路
给出⼀个数组 n,要求输出⼀个 n * n 的⼆维数组,⾥⾯元素是 1 - n*n,且数组排列顺序是螺旋排列的
class Solution {
public int[][] generateMatrix(int n) {
int l = 0, r = n - 1, t = 0, b = n - 1;
int[][] mat = new int[n][n];
int num = 1, tar = n * n;
while(num <= tar){
for(int i = l; i <= r; i++) mat[t][i] = num++; // left to right.
t++;
for(int i = t; i <= b; i++) mat[i][r] = num++; // top to bottom.
r--;
for(int i = r; i >= l; i--) mat[b][i] = num++; // right to left.
b--;
for(int i = b; i >= t; i--) mat[i][l] = num++; // bottom to top.
l++;
}
return mat;
}
}
061 旋转链表
Given a linked list, rotate the list to the right by k places, where k is non-negative.
旋转链表 K 次。
解题思路
这道题需要注意的点是,K 可能很⼤,K = 2000000000 ,如果是循环肯定会超时。应该找出 O(n) 的复杂度的算法才⾏。由于是循环旋转,最终状态其实是确定的,利⽤链表的⻓度取余可以得到链表的最终旋转结果。
这道题也不能⽤递归,递归解法会超时。
class Solution {
public ListNode rotateRight(ListNode head, int k) {
// base cases
if (head == null) return null;
if (head.next == null) return head;
// close the linked list into the ring
ListNode old_tail = head;
int n;
for(n = 1; old_tail.next != null; n++)
old_tail = old_tail.next;
old_tail.next = head;
// find new tail : (n - k % n - 1)th node
// and new head : (n - k % n)th node
ListNode new_tail = head;
for (int i = 0; i < n - k % n - 1; i++)
new_tail = new_tail.next;
ListNode new_head = new_tail.next;
// break the ring
new_tail.next = null;
return new_head;
}
}

浙公网安备 33010602011771号