二维数组的花式遍历技巧 :: labuladong的算法小抄 #1059
Replies: 56 comments 10 replies
-
48题的 // 将二维矩阵原地顺时针旋转 90 度
public void rotate(int[][] matrix) {
int n = matrix.length;
// 先沿对角线镜像对称二维矩阵
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
// swap(matrix[i][j], matrix[j][i]);
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// 然后反转二维矩阵的每一行
for (int[] row : matrix) {
reverse(row);
}
} 镜像对称那里是不是可以优化下 |
Beta Was this translation helpful? Give feedback.
-
可以优化 |
Beta Was this translation helpful? Give feedback.
-
48题 旋转图像 按照左上到右下的对角线进行镜像对称,反转二维矩阵这里应该是翻转列 // 然后反转二维矩阵的前后行
for (int[] row : matrix) {
reverse(row);
} //LC48 逆时针时针90度翻转
public void rotate1(int[][] matrix) {
int n = matrix.length;
//沿45度角对折
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][n - i - 1];
matrix[n - j - 1][n - i - 1] = temp;
}
}
//列交互元素
int left = 0, right = n - 1;
while (left < right) {
for (int i = 0; i < n; i++) {
int temp = matrix[i][left];
matrix[i][left] = matrix[i][right];
matrix[i][right] = temp;
}
left++;
right--;
}
} |
Beta Was this translation helpful? Give feedback.
-
个人常用的螺旋矩阵的遍历方式,感觉比较易懂O(∩_∩)O const constexpr int dirs[4][2]={
{0,1},{1,0},{0,-1},{-1,0}
};
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int m=matrix.size(),n=matrix[0].size();
int size=m*n;
vector<int>ans;
int i=0,j=0,curdir=0;
while(ans.size()<size){
ans.push_back(matrix[i][j]);
int ii=i+dirs[curdir][0],jj=j+dirs[curdir][1];
//越界或已访问
if(ii<0||jj<0||ii>=m||jj>=n||matrix[ii][jj]==1000){
curdir=(curdir+1)%4;
ii=i+dirs[curdir][0],jj=j+dirs[curdir][1];
}
matrix[i][j]=1000;
i=ii;
j=jj;
}
return ans;
}
}; |
Beta Was this translation helpful? Give feedback.
-
for(int i=0;i<n-1;i++) 因为最后一行的最右一个元素就是对角线上,不需要翻转,然后每一行是要从对角线往右一个元素开始计数 |
Beta Was this translation helpful? Give feedback.
-
螺旋数组,还是用模拟比较容易理解上手 public int[][] generateMatrix(int n) {
//结果数组
int[][] res = new int[n][n];
//用来模拟方向的数组
int[][] dp = {
{0, 1},
{1, 0},
{0, -1},
{-1, 0}
};
//表示用哪一个dp数组
int index = 0;
//放置访问标志
boolean[][] visited = new boolean[n][n];
int i = 0, j = 0;
int value = 1;
for (int m = 0; m < n * n; m++) {
res[i][j] = value++;
visited[i][j] = true;
//通过下一步进行判断是否需要转向
int next_i = i + dp[index][0],
next_j = j + dp[index][1];
if (next_i == n ||
next_j == n ||
next_i < 0 ||
next_j < 0 ||
visited[next_i][next_j]) {
index = (index + 1) % 4;
}
i += dp[index][0];
j += dp[index][1];
}
return res;
} |
Beta Was this translation helpful? Give feedback.
-
Golang版本螺旋矩阵II func generateMatrix(n int) [][]int {
size := n*n
matrix := make([][]int, n)
for i:=0; i<n; i++ {
matrix[i] = make([]int, n)
}
upbound, lobound, lebound, ribound := 0, n-1, 0, n-1
for cnt:=1; cnt<=size; {
if upbound <= lobound {
for i:=lebound; i<=ribound; i++ {
matrix[upbound][i] = cnt
cnt++
}
upbound++
}
if lebound <= ribound {
for i:= upbound; i<=lobound; i++ {
matrix[i][ribound] = cnt
cnt++
}
ribound--
}
if upbound <= lobound {
for i:=ribound; i>=lebound; i-- {
matrix[lobound][i] = cnt
cnt++
}
lobound--
}
if lebound <= ribound {
for i:=lobound; i>=upbound; i-- {
matrix[i][lebound] = cnt
cnt++
}
lebound++
}
}
return matrix
} |
Beta Was this translation helpful? Give feedback.
-
补充一下原地反转单词顺序的代码 public class RevertWordsInPlace {
public static String reverse(String phrase) {
return new String(reverseWords(phrase.toCharArray()));
}
private static char[] reverseWords(char[] arrays) {
// revert individual words
int start = 0;
for (int end = 0; end < arrays.length; end++) {
if (arrays[end] == ' ') {
reverse(arrays, start, end - 1);
start = end + 1;
}
}
reverse(arrays, start, arrays.length - 1);
// revert the whole phrase
reverse(arrays, 0, arrays.length - 1);
return arrays;
}
private static void reverse(char[] arrays, int start, int end) {
while (start <= end) {
swap(arrays, start, end);
start++;
end--;
}
}
private static void swap(char[] arrays, int start, int end) {
char temp = arrays[start];
arrays[start] = arrays[end];
arrays[end] = temp;
}
} |
Beta Was this translation helpful? Give feedback.
-
补充 swift 超易懂版本 func rotate(_ matrix: inout [[Int]]) {
var n = matrix.count
// 对角线镜像数组
for i in 0..<n {
for j in i..<n {
let tmp = matrix[i][j]
matrix[i][j] = matrix[j][i]
matrix[j][i] = tmp
}
}
// 反转数组每一行
for i in 0..<n {
matrix[i].reverse()
}
} |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
@ichengzi 👍👍 |
Beta Was this translation helpful? Give feedback.
-
关于矩阵旋转,我是否可以这样操作呢:顺时针旋转90°就是先沿主对角线镜像翻转,然后reverse;逆时针旋转90°就是先reverse,然后在沿主对角线镜像翻转。(主要是我想规避我理不清逆时针旋转里数组角标的问题哈哈哈哈) |
Beta Was this translation helpful? Give feedback.
-
48题为什么用swap就不行呢,我手写交换函数,发现无法让数组实现交换,直接在for里写交换就行,不明白(就是注释掉地的那一行) |
Beta Was this translation helpful? Give feedback.
-
Python的: def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
for i in range(n):
for j in range(i,n):
matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]
for i in range(n):
_L = 0
_R = n - 1
while _L<_R:
matrix[i][_L],matrix[i][_R] = matrix[i][_R],matrix[i][_L]
_L = _L + 1
_R = _R - 1 |
Beta Was this translation helpful? Give feedback.
-
打卡 2022.4.18 |
Beta Was this translation helpful? Give feedback.
-
妙啊 |
Beta Was this translation helpful? Give feedback.
-
杀了我吧 用84厘米大砍刀 |
Beta Was this translation helpful? Give feedback.
-
分享一下我 54题【Spiral Matrix】的解法
|
Beta Was this translation helpful? Give feedback.
-
建立二维坐标系
int[][] matrix为N*N矩阵
参考代码 /**
* 顺时针旋转90度 (i,j)-->(j,-i)
*/
Cell[][] rotate90(){
Cell[][] cellMatrix = buildCell(matrix);
Cell[][] result = new Cell[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
result[i][j] = cellMatrix[i][j].rotate90();
}
}
return result;
}
/**
* 根据原始矩阵构建,坐标系矩阵
* @param matrix
* @return
*/
private Cell[][] buildCell(int[][] matrix){
Cell[][] res = new Cell[N][N];
int half = N/2;
int ci,cj;
for (int i = 0; i < N; i++) {
ci = -half;
cj = half - i;
for (int j = 0; j < N; j++) {
res[i][j] = new Cell(ci++,cj,matrix[i][j]);
}
}
return res;
}
class Cell{
int x;
int y;
int val;
Cell(int x,int y, int val){
this.x = x;
this.y = y;
this.val = val;
}
/**
* 顺时针旋转90度 (x,y)-->(y,-x)
*/
public Cell rotate90(){
return new Cell(y,-x,val);
}
public Cell rotate180(){
return new Cell(-x,-y,val);
}
public Cell rotate270(){
return new Cell(-y,x,val);
}
protected Cell clone(){
return new Cell(x,y,val);
}
} |
Beta Was this translation helpful? Give feedback.
-
public class LeetCode151 {
public static String reverseWords(String s) {
// 切除s的首尾空格
String trimS = s.trim();
// 翻转一整个字符串。
StringBuilder reversedString = new StringBuilder();
for (int i = trimS.length() - 1; i >= 0; i--) {
reversedString.append(trimS.charAt(i));
}
String tmp1 = reversedString.toString();
// 将翻转后的字符串按空格切割。
String[] s1 = tmp1.split(" ");
// 翻转切割后的每个单字符串
StringBuilder reverse = new StringBuilder();
for (int i = 0; i < s1.length; i++) {
if (!s1[i].equals("")) { // 因为字符串中间可能有多个空格,只关注非空格的部分。
for (int j = s1[i].length() - 1; j >= 0; j--) {
reverse.append(s1[i].charAt(j));
}
reverse.append(" ");
}
}
// 最后一个字符串也会导致多增加一个尾部空格,去除尾部空格。
String res = reverse.toString().trim();
return res;
}
public static void main(String[] args) {
String s = "a good example";
System.out.println(reverseWords(s));
}
} |
Beta Was this translation helpful? Give feedback.
-
打卡 |
Beta Was this translation helpful? Give feedback.
-
const arr = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[7, 6, 5, 4],
[4, 1, 2, 3],
];
const n = arr.length;
// 1. 按照左上角到右上角翻转
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (i < j) {
[arr[i][j], arr[j][i]] = [arr[j][i], arr[i][j]];
}
}
}
for (let i = 0; i < n; i++) {
for (let j = 0; j <= Math.floor(n / 2); j++) {
[arr[i][j], arr[i][n - 1 - j]] = [arr[i][n - 1 - j], arr[i][j]];
}
} |
Beta Was this translation helpful? Give feedback.
-
感觉螺旋数组while-loop的执行条件可以优化为 |
Beta Was this translation helpful? Give feedback.
-
C++ 螺旋矩阵DP版本
void dp(vector<vector<int>>& matrix, int start, int upper, int low,int left, int right){
if(upper>low||left>right) return;
for(int i=left;i<=right;i++){
matrix[upper][i] = start++;
}
for(int i = upper+1;i<=low;i++){
matrix[i][right] = start++;
}
for(int i = right-1;i>=left;i--){
if(upper!= low) matrix[low][i]=start++;
}
for(int i =low-1;i>upper;i--){
if(left!=right) matrix[i][left]=start++;
}
dp(matrix,start,upper+1,low-1,left+1,right-1);
}
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n));
dp(res,1,0,n-1,0,n-1);
return res;
} |
Beta Was this translation helpful? Give feedback.
-
二维数组又玩出了花! |
Beta Was this translation helpful? Give feedback.
-
其实54题中的前面两个if判断是不需要的,如下代码也可以通过:
|
Beta Was this translation helpful? Give feedback.
-
翻转字符串的C语言版,可以去除多余空格 //实现原地翻转并去除多余空格
//把从end开始倒数length个字符逆序复制到begin位置
void swapChars(char* arr,int begin,int end,int length){
char ch;
while(begin<end&&length--){
ch=arr[begin];
arr[begin]=arr[end];
arr[end]=ch;
++begin;
--end;
}
}
char* reverseWords(char* s) {
int slow=0,fast=0;
int length=(int)strlen(s),wordLen=0;
//先翻转整个字符串
swapChars(s,0,length-1,length);
while(fast<length){
if(s[fast]==' '&&fast!=0&&s[fast-1]!=' '){
swapChars(s,slow,fast-1,wordLen);
//slow要走到翻转的这个单词后的第二个位置,因为每个单词间要有一个空格
slow+=wordLen+1;
wordLen=0;
}
if(s[fast]!=' '){
++wordLen;
}
++fast;
}
//如果字符串末尾不是空格说明最后一个单词还没有翻转
if(s[fast-1]!=' '){
swapChars(s,slow,fast-1,wordLen);
slow+=wordLen+1;
}
//因为slow走到了最后一个单词后的第二个位置,在上一个位置放置字符串结束符,后面的空格不要了
s[slow-1]='\0';
return s;
} |
Beta Was this translation helpful? Give feedback.
-
好像螺旋矩阵的那道题的while循环并不能起到真正控制循环次数的作用,边界控制和元素总和控制二选一就可以了。如果真的想要用res的容量控制,可以int count = 0。每次添加元素的时候count++,并且把count<元素总和写到每个for循环里去。这样就可以把四个类似 if (left_bound <= right_bound) 这样的边界控制语句全删了。 |
Beta Was this translation helpful? Give feedback.
-
不是原地反转字符串,但是简单的golang解法(反转字符串再反转单词) func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
// 反转单词顺序
func reverseWords(s string) string {
// 首先反转整个字符串
reversed := reverseString(s)
// 分割字符串
parts := strings.Split(reversed, " ")
var res []string
// 反转每个单词
for _, part := range parts {
if part != "" {
res = append(res, reverseString(part))
}
}
// 用空格拼接单词
return strings.Join(res, " ")
} |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:二维数组的花式遍历技巧
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions