1. 矩陣置零(t73)
中等難度,題目示例如下:
給定一個 m x n 的矩陣,如果一個元素為 0 ,則將其所在行和列的所有元素都設為 0 。請使用原地算法。示例 1:
輸入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
輸出:[[1,0,1],[0,0,0],[1,0,1]]示例 2:
輸入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
輸出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
思路分析:看到這題,一個樸素的思想是,只要遇到 0 的元素就去查詢同行同列,但這樣操作搜索的復雜度過高。看題解可以采用一個標記數組,相當于復制一個矩陣,如果遇到有元素為0,就將其行和列標記為true
,最后再遍歷一次矩陣,對標記的部分置零。
class Solution {
public:void setZeroes(vector<vector<int>>& matrix) {int m = matrix.size();int n = matrix[0].size();vector<int> row(m), col(n);for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (!matrix[i][j]) {row[i] = col[j] = true;}}}for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (row[i] || col[j]) {matrix[i][j] = 0;}}}}
};
2. 螺旋矩陣(t54)
中等難度,題目示例如下:
給你一個 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:vector<int> spiralOrder(vector<vector<int>>& matrix) {vector<int> ans;if (matrix.empty()) return ans;int rows = matrix.size();int cols = matrix[0].size();int up = 0, down = rows - 1;int left = 0, right = cols - 1;while (true) {// 向右for (int i = left; i <= right; i++) {ans.push_back(matrix[up][i]);}up++;if (up > down) break;// 向下for (int i = up; i <= down; i++) {ans.push_back(matrix[i][right]);}right--;if (right < left) break;// 向左for (int i = right; i >= left; i--) {ans.push_back(matrix[down][i]);}down--;if (down < up) break;// 向上for (int i = down; i >= up; i--) {ans.push_back(matrix[i][left]);}left++;if (left > right) break;}return ans;}
};
3. 旋轉圖像(t48)
中等難度,題目示例如下:
給定一個 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]]
思路分析:這題最簡單的思路就是直接找旋轉的圖像的規律,仔細觀察就可以發現,旋轉這個操作,等價于對角線翻轉+左右翻轉。下面稍微注意的是,做對角線翻轉只需要遍歷矩陣的上三角。
class Solution {
public:void rotate(vector<vector<int>>& matrix) {int rows = matrix.size();int cols = matrix[0].size();// 對角線翻轉for (int i = 0; i < rows; i++){for (int j = i; j < cols; j++){swap(matrix[i][j], matrix[j][i]);}}// 左右翻轉for (int i = 0; i < rows; i++){for (int j = 0; j < cols / 2; j++){swap(matrix[i][j], matrix[i][cols - 1 - j]);}}}
};
4. 搜索二維矩陣 II(t240)
中等難度,題目示例如下:
編寫一個高效的算法來搜索 m x n 矩陣 matrix 中的一個目標值 target 。該矩陣具有以下特性:每行的元素從左到右升序排列。
每列的元素從上到下升序排列。示例:
輸入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
輸出:true
思路分析:這道題直接用暴力法很容易求解,可以直接按先列后行的順序搜索,一旦遇到大于 target 的值,就提前跳出,節省時間。
class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int rows = matrix.size();int cols = matrix[0].size();for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){if (matrix[i][j] == target) return true;else if (matrix[i][j] > target) break; }}return false;}
};
題目中,每行每列都已經是排序好的,因此顯然存在更優方案,看了用戶 Krahets 的題解恍然大悟,把矩陣逆時針旋轉 45°,就變成了類似二叉搜索樹的結構。
因此,可以從矩陣的左下角出發,如果左下角大于target,則往上移動一行,如果小于target,則可以直接往右搜索。
class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int i = matrix.size() - 1, j = 0;while(i >= 0 && j < matrix[0].size()){if(matrix[i][j] > target) i--;else if(matrix[i][j] < target) j++;else return true;}return false;}
};