劍指Offer | 搜尋與回溯演算法
阿新 • • 發佈:2021-10-22
劍指 Offer 12. 矩陣中的路徑
給定一個 m x n
二維字元網格 board
和一個字串單詞 word
。如果 word
存在於網格中,返回 true
;否則,返回 false
。
單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重複使用。
例如,在下面的 3×4 的矩陣中包含單詞 "ABCCED"(單詞中的字母已標出)。
示例 :
輸入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" 輸出:true
提示:
1 <= board.length <= 200
1 <= board[i].length <= 200
board
和word
僅由大小寫英文字母組成
方法:深度搜索+剪枝
class Solution { public: bool exist(vector<vector<char>>& board, string word) { // 此處的 row 和 col 是this 指標下的成員,前面一定不可以加int row = board.size(); col = board[0].size(); for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { // 如果以當前節點作為單詞頭能找到匹配的路徑,則返回true if(dfs(board, word, i, j, 0)) return true; } } return false; } private: int row, col; bool dfs(vector<vector<char>>& board, string word, int i, int j, int k) { // 判斷越界和不符的情況 if(i>=row || i<0 || j>=col || j<0 || board[i][j]!=word[k])return false; if(k == word.size()-1) return true; // 跳出了第一句判斷,說明兩邊的字元相匹配,因此將該值暫時賦值'\0',方便後面匹配 board[i][j] = '\0'; bool res = dfs(board, word, i+1, j, k+1) || dfs(board, word, i-1, j, k+1) || dfs(board, word, i, j-1, k+1) || dfs(board, word, i, j+1, k+1); // 還原之前被置為'\0'的字元,被置為'\0'一定是因為字元相匹配,所以還原時也可以直接賦值 board[i][j] = word[k]; return res; } };
參考:
劍指 Offer 13. 機器人的運動範圍
地上有一個m行n列的方格,從座標 [0,0]
到座標 [m-1,n-1]
。一個機器人從座標 [0, 0]
的格子開始移動,它每次可以向左、右、上、下移動一格(不能移動到方格外),也不能進入行座標和列座標的數位之和大於k的格子。例如,當k為18時,機器人能夠進入方格 [35, 37] ,因為3+5+3+7=18。但它不能進入方格 [35, 38],因為3+5+3+8=19。請問該機器人能夠到達多少個格子?
示例 :
輸入:m = 2, n = 3, k = 1
輸出:3
提示:
1 <= n,m <= 100
0 <= k <= 20
方法:深度搜索
class Solution {
public:
int movingCount(int m, int n, int k) {
// 建立輔助陣列 visited
vector<vector<bool>> visited(m, vector<bool>(n, 0));
return dfs(visited, m, n, 0, 0, k);
}
int dfs(vector<vector<bool>>& visited, int m, int n, int i, int j, int k) {
// 遇到非法情況,返回0
if(i>=m|| j>=n || !isLegal(i, j, k) || visited[i][j]) return 0;
// 否則選中,將該位置的 visited 置為 true
visited[i][j] = true;
// 然後往下和往右遍歷
return 1 + dfs(visited, m, n, i+1, j, k) + dfs(visited, m, n, i, j+1, k);
}
// 行列之和與k比較,判斷合法性
bool isLegal(int i, int j, int k) {
int sum = 0;
while(i != 0) {
sum += i % 10;
i /= 10;
}
while(j != 0) {
sum += j % 10;
j /= 10;
}
return (sum > k) ? false : true;
}
};