旋转图像
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
示例 3:
输入:matrix = [[1]]
输出:[[1]]
示例 4:
输入:matrix = [[1,2],[3,4]]
输出:[[3,1],[4,2]]
模拟法
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < n / 2; i++) {
for (int j = 0; j < (n + 1) / 2; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = temp;
}
}
}
}
螺旋矩阵
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
模拟法
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> order = new ArrayList<Integer>();
int rows = matrix.length, columns = matrix[0].length;
boolean[][] visited = new boolean[rows][columns];
int total = rows * columns;
int directionIndex = 0;
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int cur_row = 0, cur_col = 0;
for (int i = 0; i < total; i++) {
order.add(matrix[cur_row][cur_col]);
visited[cur_row][cur_col] = true;
int nextRow = cur_row + directions[directionIndex][0];
int nextCol = cur_col + directions[directionIndex][1];
if (nextRow < 0 || nextRow >= rows || nextCol < 0 || nextCol >= columns || visited[nextRow][nextCol]) {
directionIndex = (directionIndex + 1) % 4;
}
cur_row += directions[directionIndex][0];
cur_col += directions[directionIndex][1];
}
return order;
}
}
按层模拟
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> order = new ArrayList<Integer>();
int rows = matrix.length, columns = matrix[0].length;
int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
while (left <= right && top <= bottom) {
for (int col = left; col <= right; col++) {
order.add(matrix[top][col]);
}
for (int row = top + 1; row <= bottom; row++) {
order.add(matrix[row][right]);
}
if (left < right && top < bottom) {
for (int col = right - 1; col > left; col--) {
order.add(matrix[bottom][col]);
}
for (int row = bottom; row > top; row--) {
order.add(matrix[row][left]);
}
}
left++;
right--;
top++;
bottom--;
}
return order;
}
}
螺旋矩阵2
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1
输出:[[1]]
模拟
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
boolean[][] visited = new boolean[n][n];
int total = n * n;
int directionIndex = 0;
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int cur_row = 0, cur_col = 0;
for (int i = 1; i <= total; i++) {
matrix[cur_row][cur_col] = i;
visited[cur_row][cur_col] = true;
int nextRow = cur_row + directions[directionIndex][0];
int nextCol = cur_col + directions[directionIndex][1];
if (nextRow < 0 || nextRow >= n || nextCol < 0 || nextCol >= n || visited[nextRow][nextCol]) {
directionIndex = (directionIndex + 1) % 4;
}
cur_row += directions[directionIndex][0];
cur_col += directions[directionIndex][1];
}
return matrix;
}
}
按层模拟
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
int num = 1;
int left = 0, right = n - 1, top = 0, bottom = n - 1;
while (num <= n * n) {
for (int col = left; col <= right; col++)
matrix[top][col] = num++;
for (int row = top + 1; row <= bottom; row++)
matrix[row][right] = num++;
for (int col= right - 1; col > left; col--)
matrix[bottom][col] = num++;
for (int row = bottom; row > top; row--)
matrix[row][left] = num++;
left++;
right--;
top++;
bottom--;
}
return matrix;
}
}
重塑矩阵
在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。
示例 1:
输入:
nums =
[[1,2],
[3,4]]
r = 1, c = 4
输出:
[[1,2,3,4]]
解释:
行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。
示例 2:
输入:
nums =
[[1,2],
[3,4]]
r = 2, c = 4
输出:
[[1,2],
[3,4]]
解释:
没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。
模拟
class Solution {
public int[][] matrixReshape(int[][] mat, int r, int c) {
int row = mat.length, col = mat[0].length;
if (row * col != r * c)
return mat;
int[][] newMat = new int[r][c];
for (int i = 0; i < r * c; i++)
newMat[i / c][i % c] = mat[i / col][i % col];
return newMat;
}
}
猜数字游戏
你在和朋友一起玩 猜数字(Bulls and Cows)游戏,该游戏规则如下:
- 你写出一个秘密数字,并请朋友猜这个数字是多少。
- 朋友每猜测一次,你就会给他一个提示,告诉他的猜测数字中有多少位属于数字和确切位置都猜对了(称为“Bulls”, 公牛),有多少位属于数字猜对了但是位置不对(称为“Cows”, 奶牛)。
- 朋友根据提示继续猜,直到猜出秘密数字。
请写出一个根据秘密数字和朋友的猜测数返回提示的函数,返回字符串的格式为 xAyB ,x 和 y 都是数字,A 表示公牛,用 B 表示奶牛。
- xA 表示有 x 位数字出现在秘密数字中,且位置都与秘密数字一致。
- yB 表示有 y 位数字出现在秘密数字中,但位置与秘密数字不一致。
请注意秘密数字和朋友的猜测数都可能含有重复数字,每位数字只能统计一次。
示例 1:
输入: secret = “1807”, guess = “7810”
输出: “1A3B”
解释: 1 公牛和 3 奶牛。公牛是 8,奶牛是 0, 1 和 7。
示例 2:
输入: secret = “1123”, guess = “0111”
输出: “1A1B”
解释: 朋友猜测数中的第一个 1 是公牛,第二个或第三个 1 可被视为奶牛。
两次遍历
class Solution {
public String getHint(String secret, String guess) {
int bull = 0, cow = 0;
int len = secret.length();
int[] sList = new int[10], gList = new int[10];
char[] sChars = secret.toCharArray(), gChars = guess.toCharArray();
for (int i = 0; i < len; i++) {
if (sChars[i] == gChars[i]) {
bull++;
} else {
sList[sChars[i] - '0']++;
gList[gChars[i] - '0']++;
}
}
for (int i = 0; i < 10; i++)
cow += Math.min(sList[i], gList[i]);
StringBuilder sb = new StringBuilder();
sb.append(bull).append('A').append(cow).append('B');
return sb.toString();
}
}
一次遍历
secret 中的数字记录为正,guess中的数字记录为负。
class Solution {
public String getHint(String secret, String guess) {
int bull = 0, cow = 0;
int len = secret.length();
int[] count = new int[10];
char[] sChars = secret.toCharArray(), gChars = guess.toCharArray();
for (int i = 0; i < len; i++) {
if (sChars[i] == gChars[i]) {
bull++;
} else {
if (count[sChars[i] - '0']++ < 0)
cow++;
if (count[gChars[i] - '0']-- > 0)
cow++;
}
}
StringBuilder sb = new StringBuilder();
sb.append(bull).append('A').append(cow).append('B');
return sb.toString();
}
}
神奇字符串
神奇的字符串 S 只包含 ‘1’ 和 ‘2’,并遵守以下规则:
- 字符串 S 是神奇的,因为串联字符 ‘1’ 和 ‘2’ 的连续出现次数会生成字符串 S 本身。
- 字符串 S 的前几个元素如下:S = “1221121221221121122 …”
- 如果我们将 S 中连续的 1 和 2 进行分组,它将变成:
1 22 11 2 1 22 1 22 11 2 11 22 …
并且每个组中 ‘1’ 或 ‘2’ 的出现次数分别是:
1 2 2 1 1 2 1 2 2 1 2 2 …
你可以看到上面的出现次数就是 S 本身。
给定一个整数 N 作为输入,返回神奇字符串 S 中前 N 个数字中的 ‘1’ 的数目。
注意:N 不会超过 100,000。
示例:
输入:6
输出:3
解释:神奇字符串 S 的前 6 个元素是 “12211”,它包含三个 1,因此返回 3。
模拟+双指针
class Solution {
public int magicalString(int n) {
int[] string = new int[n + 3];
string[0] = 1; string[1] = 2; string[2] = 2;
int i = 2, pos = 3, count = 1, digit = 2;
while (pos < n) {
digit = 3 - digit;
int k = string[i++];
if (digit == 1)
count += k;
while (k-- > 0)
string[pos++] = digit;
}
if (pos > n && digit == 1)
count -= pos - n;
return count;
}
}
FizzBuzz
写一个程序,输出从 1 到 n 数字的字符串表示。
- 如果 n 是3的倍数,输出“Fizz”;
- 如果 n 是5的倍数,输出“Buzz”;
- 如果 n 同时是3和5的倍数,输出 “FizzBuzz”。
示例:
n = 15,
返回:
[
“1”,
“2”,
“Fizz”,
“4”,
“Buzz”,
“Fizz”,
“7”,
“8”,
“Fizz”,
“Buzz”,
“11”,
“Fizz”,
“13”,
“14”,
“FizzBuzz”
]
模拟
class Solution {
public List<String> fizzBuzz(int n) {
List<String> result = new ArrayList<>();
for (int i = 1; i <= n; i++) {
if (i % 3 == 0 && i % 5 == 0)
result.add("FizzBuzz");
else if (i % 3 == 0)
result.add("Fizz");
else if (i % 5 == 0)
result.add("Buzz");
else
result.add(String.valueOf(i));
}
return result;
}
}