日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二维数组的花式遍历技巧盘点

發布時間:2024/1/8 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二维数组的花式遍历技巧盘点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學算法認準?labuladong

后臺回復?進群?進刷題

讀完本文,可以去力扣解決如下題目:

48. 旋轉圖像(中等)

54. 螺旋矩陣(中等)

59. 螺旋矩陣 II(中等)

有不少讀者說,看過很多公眾號歷史文章之后掌握了框架思維,可以解決大部分有套路框架可循的題目。

但是框架思維也不是萬能的,有一些特定技巧呢,屬于會者不難,難者不會的類型,只能通過多刷題進行總結和積累。

那么本文我分享一些巧妙的二維數組的花式操作,你只要有個印象,以后遇到類似題目就不會懵圈了。

順/逆時針旋轉矩陣

對二維數組進行旋轉是常見的筆試題,力扣第 48 題「旋轉圖像」就是很經典的一道:

題目很好理解,就是讓你將一個二維矩陣順時針旋轉 90 度,難點在于要「原地」修改,函數簽名如下:

void?rotate(int[][]?matrix)

如何「原地」旋轉二維矩陣?稍想一下,感覺操作起來非常復雜,可能要設置巧妙的算法機制來「一圈一圈」旋轉矩陣:

但實際上,這道題不能走尋常路,在講巧妙解法之前,我們先看另一道谷歌曾經考過的算法題熱熱身:

給你一個包含若干單詞和空格的字符串s,請你寫一個算法,原地反轉所有單詞的順序。

比如說,給你輸入這樣一個字符串:

s?=?"hello?world?labuladong"

你的算法需要原地反轉這個字符串中的單詞順序:

s?=?"labuladong?world?hello"

常規的方式是把s按空格split成若干單詞,然后reverse這些單詞的順序,最后把這些單詞join成句子。但這種方式使用了額外的空間,并不是「原地反轉」單詞。

正確的做法是,先將整個字符串s反轉

s?=?"gnodalubal?dlrow?olleh"

然后將每個單詞分別反轉

s?=?"labuladong?world?hello"

這樣,就實現了原地反轉所有單詞順序的目的。

我講這道題的目的是什么呢?

旨在說明,有時候咱們拍腦袋的常規思維,在計算機看來可能并不是最優雅的;但是計算機覺得最優雅的思維,對咱們來說卻不那么直觀。也許這就是算法的魅力所在吧。

回到之前說的順時針旋轉二維矩陣的問題,常規的思路就是去尋找原始坐標和旋轉后坐標的映射規律,但我們是否可以讓思維跳躍跳躍,嘗試把矩陣進行反轉、鏡像對稱等操作,可能會出現新的突破口。

我們可以先將n x n矩陣matrix按照左上到右下的對角線進行鏡像對稱

然后再對矩陣的每一行進行反轉

發現結果就是matrix順時針旋轉 90 度的結果

將上述思路翻譯成代碼,即可解決本題:

//?將二維矩陣原地順時針旋轉?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);} }//?反轉一維數組 void?reverse(int[]?arr)?{int?i?=?0,?j?=?arr.length?-?1;while?(j?>?i)?{//?swap(arr[i],?arr[j]);int?temp?=?arr[i];arr[i]?=?arr[j];arr[j]?=?temp;i++;j--;} }

肯定有讀者會問,如果沒有做過這道題,怎么可能想到這種思路呢?

其實我覺得這個思路還是挺容易想出來的,如果學過線性代數,這道算法題的思路本質就是矩陣變換,肯定可以想出來。

即便沒學過線性代數,旋轉二維矩陣的難點在于將「行」變成「列」,將「列」變成「行」,而只有按照對角線的對稱操作是可以輕松完成這一點的,對稱操作之后就很容易發現規律了。

既然說道這里,我們可以發散一下,如何將矩陣逆時針旋轉 90 度呢

思路是類似的,只要通過另一條對角線鏡像對稱矩陣,然后再反轉每一行,就得到了逆時針旋轉矩陣的結果:

翻譯成代碼如下:

//?將二維矩陣原地逆時針旋轉?90?度 void?rotate2(int[][]?matrix)?{int?n?=?matrix.length;//?沿左下到右上的對角線鏡像對稱二維矩陣for?(int?i?=?0;?i?<?n;?i++)?{for?(int?j?=?0;?j?<?n?-?i;?j++)?{//?swap(matrix[i][j],?matrix[n-j-1][n-i-1])int?temp?=?matrix[i][j];matrix[i][j]?=?matrix[n?-?j?-?1][n?-?i?-?1];matrix[n?-?j?-?1][n?-?i?-?1]?=?temp;}}//?然后反轉二維矩陣的每一行for?(int[]?row?:?matrix)?{reverse(row);} }void?reverse(int[]?arr)?{?/*?見上文?*/}

至此,旋轉矩陣的問題就解決了。

矩陣的螺旋遍歷

我的公眾號 動態規劃系列文章 經常需要遍歷二維dp數組,但難點在于狀態轉移方程而不是數組的遍歷,頂多就是倒序遍歷。

今天我們講一下力扣第 54 題「螺旋矩陣」,看一看二維矩陣可以如何花式遍歷:

函數簽名如下:

List<Integer>?spiralOrder(int[][]?matrix)

解題的核心思路是按照右、下、左、上的順序遍歷數組,并使用四個變量圈定未遍歷元素的邊界

隨著螺旋遍歷,相應的邊界會收縮,直到螺旋遍歷完整個數組:

只要有了這個思路,翻譯出代碼就很容易了:

List<Integer>?spiralOrder(int[][]?matrix)?{int?m?=?matrix.length,?n?=?matrix[0].length;int?upper_bound?=?0,?lower_bound?=?m?-?1;int?left_bound?=?0,?right_bound?=?n?-?1;List<Integer>?res?=?new?LinkedList<>();//?res.size()?==?m?*?n?則遍歷完整個數組while?(res.size()?<?m?*?n)?{if?(upper_bound?<=?lower_bound)?{//?在頂部從左向右遍歷for?(int?j?=?left_bound;?j?<=?right_bound;?j++)?{res.add(matrix[upper_bound][j]);}//?上邊界下移upper_bound++;}if?(left_bound?<=?right_bound)?{//?在右側從上向下遍歷for?(int?i?=?upper_bound;?i?<=?lower_bound;?i++)?{res.add(matrix[i][right_bound]);}//?右邊界左移right_bound--;}if?(upper_bound?<=?lower_bound)?{//?在底部從右向左遍歷for?(int?j?=?right_bound;?j?>=?left_bound;?j--)?{res.add(matrix[lower_bound][j]);}//?下邊界上移lower_bound--;}if?(left_bound?<=?right_bound)?{//?在左側從下向上遍歷for?(int?i?=?lower_bound;?i?>=?upper_bound;?i--)?{res.add(matrix[i][left_bound]);}//?左邊界右移left_bound++;}}return?res; }

力扣第 59 題「螺旋矩陣 II」也是類似的題目,只不過是反過來,讓你按照螺旋的順序生成矩陣:

函數簽名如下:

int[][]?generateMatrix(int?n)

有了上面的鋪墊,稍微改一下代碼即可完成這道題:

int[][]?generateMatrix(int?n)?{int[][]?matrix?=?new?int[n][n];int?upper_bound?=?0,?lower_bound?=?n?-?1;int?left_bound?=?0,?right_bound?=?n?-?1;//?需要填入矩陣的數字int?num?=?1;while?(num?<=?n?*?n)?{if?(upper_bound?<=?lower_bound)?{//?在頂部從左向右遍歷for?(int?j?=?left_bound;?j?<=?right_bound;?j++)?{matrix[upper_bound][j]?=?num++;}//?上邊界下移upper_bound++;}if?(left_bound?<=?right_bound)?{//?在右側從上向下遍歷for?(int?i?=?upper_bound;?i?<=?lower_bound;?i++)?{matrix[i][right_bound]?=?num++;}//?右邊界左移right_bound--;}if?(upper_bound?<=?lower_bound)?{//?在底部從右向左遍歷for?(int?j?=?right_bound;?j?>=?left_bound;?j--)?{matrix[lower_bound][j]?=?num++;}//?下邊界上移lower_bound--;}if?(left_bound?<=?right_bound)?{//?在左側從下向上遍歷for?(int?i?=?lower_bound;?i?>=?upper_bound;?i--)?{matrix[i][left_bound]?=?num++;}//?左邊界右移left_bound++;}}return?matrix; }

至此,兩道螺旋矩陣的題目也解決了。

以上就是遍歷二維數組的一些技巧,其他數組技巧可參見之前的文章 前綴和數組,差分數組,數組雙指針算法集合;鏈表相關技巧可參見 單鏈表六大算法技巧匯總。?

_____________

公眾號后臺回復關鍵詞「目錄」查看精選歷史文章,另外沒關注我視頻號的讀者趕緊關注下,每周末有空直播:

總結

以上是生活随笔為你收集整理的二维数组的花式遍历技巧盘点的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。