Leetcode C++ 二叉树&递归
Leetecode 17
17. Letter Combinations of a Phone Number
Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.
A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.
- 思路:
首先画出递归树,该问题类似排列问题,要在循环中调用递归函数。
const unordered_map<char, string> num2str =
{{'2', "abc"},
{'3', "def"},
{'4', "ghi"},
{'5', "jkl"},
{'6', "mno"},
{'7', "pqrs"},
{'8', "tuv"},
{'9', "wxyz"}};
void combinationCore(string digits, int index, string& word, vector<string>& res) {
string letters = num2str[digits.at(index)];
for (int i = 0; i < letters.length(); ++ i) {
word += letters.at(i);
if (word.length() == digits.length()) { // 得到一个解的条件
res.push_back(word);
} else {
combinationCore(digits, index + 1, word, res); // 递归调用
}
word.pop_back();
}
}
vector<string> letterCombinations(string digits) {
vector<string> res;
if (!digits.length())
return res;
string word = "";
combinationCore(digits, 0, word, res);
return res;
}
Leetecode 46
46. Permutations
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.
Example 1:
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
- 思路:
经典排列问题,使用递归方法。
**注意:**使用used变量记录元素是否已经使用过。
void permuteCore(vector<int>& nums, vector<int>& p, vector<bool>& used, vector<vector<int> >& res) {
if (p.size() == nums.size())
res.push_back(p);
else {
for (int i = 0; i < nums.size(); ++i) {
if (!used[i]) {
p.push_back(nums[i]);
used[i] = true;
permuteCore(nums, p, used, res);
p.pop_back();
used[i] = false;
}
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int> > res;
if (!nums.size())
return res;
vector<int> p;
vector<bool> used(nums.size(), false);
permuteCore(nums, p, used, res);
return res;
Leetecode 77
77. Combinations
Given two integers n and k, return all possible combinations of k numbers out of 1 … n.
You may return the answer in any order.
Example 1:
Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
- 思路:
经典组合问题,使用递归方法。画出问题的递归树。
void combineCore(int n, int k, int start, vector<int>& c, vector<vector<int> >& res) {
if (c.size() == k)
res.push_back(c);
else {
for (int i = start; i <= n; ++i) {
c.push_back(i);
combineCore(n, k, i + 1, c, res);
c.pop_back();
}
}
}
vector<vector<int>> combine(int n, int k) {
vector<vector<int> > res;
if (n < 1 || n < k || k < 1)
return res;
vector<int> c;
combineCore(n, k, 1, c, res);
return res;
Leetecode 79
79. Word Search
Given an m x n grid of characters board and a string word, return true if word exists in the grid.
The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.
- 思路:
通过DFS解决二维平面问题,该问题中的技巧是递归的结束方法。在第一次得到满足要求的序列后,即可结束递归过程,方法是为递归函数设置返回值,在循环中调用递归函数时设置if语句判断递归返回值,当出现满足条件的情况时即可实现递归式返回,提前结束循环过程。
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
m_ = board.size();
n_ = board[0].size();
for (int i = 0; i < m_; ++ i)
visited_.push_back(vector<bool>(n_, false));
for (int i = 0; i < m_; ++ i) {
for (int j = 0; j < n_; ++ j) {
// cout << "i, j = " << i << ", " << j << ";";
if (dfs(board, i, j, 0, word))
return true;
}
}
return false;
}
private:
// 设置递归返回值
// 以(i,j)为起点寻找word[index,...]字符串
bool dfs(vector<vector<char>>& board, int i, int j, int index, string& word) {
if (index == word.length()) {
return true;
}
if (inArea(i, j) && !visited_[i][j] && board[i][j] == word.at(index)) {
visited_[i][j] = true;
//cout << board[i][j] << ", ";
for (int m_id = 0; m_id < 4; ++ m_id) {
int new_i = i + move[m_id][0];
int new_j = j + move[m_id][1];
// 通过if实现递归式返回,提前结束循环;
if (dfs(board, new_i, new_j, index + 1, word))
return true;
}
visited_[i][j] = false;
}
return false;
}
bool inArea(int i, int j) {
if (0 <= i && i < m_ && 0 <= j && j < n_)
return true;
return false;
}
int m_, n_;
int move[4][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
vector<vector<bool> > visited_;
};
Leetecode 200
200. Number of Islands
Given an m x n 2D binary grid grid which represents a map of '1’s (land) and '0’s (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
Input: grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
Output: 1
- 思路:
floodfill算法,DFS在二位平面中的经典应用。
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int res = 0;
m_ = grid.size();
n_ = grid[0].size();
for (int i = 0; i < m_; ++ i)
visited_.push_back(vector<bool>(n_, false));
for (int i = 0; i < m_; ++ i) {
for (int j = 0; j < n_; ++j) {
if (grid[i][j] == '1' && !visited_[i][j]) {
dfs(grid, i, j);
res++;
}
}
}
return res;
}
private:
int m_, n_;
vector<vector<bool> > visited_;
int move_[4][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
bool inArea(int i, int j) {
return 0 <= i && i < m_ && 0 <= j && j < n_;
}
void dfs(vector<vector<char> >& grid, int i, int j) {
visited_[i][j] = true; // 设置标记
// cout << "i, j: " << i << ", " << j << ";";
for (int m = 0; m < 4; ++ m) {
int new_i = i + move_[m][0];
int new_j = j + move_[m][1];
if (inArea(new_i, new_j) && grid[new_i][new_j] == '1' && !visited_[new_i][new_j])
dfs(grid, new_i, new_j);
}
//visited_[i][j] = false;
}
};
Leetecode 51
51. N-Queens
The n-queens puzzle is the problem of placing n queens on an n x n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space, respectively.
- 思路:
经典N-皇后问题,使用DFS方法。
// 检查在棋盘chessboard的(i,i)位置是否可以放置皇后棋子
bool checkPuts(vector<string>& chessboard, int i, int j) {
int n = chessboard.size();
int row = i;
int left_col = j;
int right_col = j;
while (--row >= 0) {
// check same column
if (chessboard[row].at(j) == 'Q')
return false;
// check left diag
if (--left_col >= 0)
if (chessboard[row].at(left_col) == 'Q')
return false;
// check right diag
if (++right_col < n)
if (chessboard[row].at(right_col) == 'Q')
return false;
}
return true;
}
// 注意递归树中层数通过函数参数传递,每层的分支树为内层for循环
void NQueens(int row, vector<string>& chessboard, vector<vector<string> >& res) {
if (row == chessboard.size()) {
res.push_back(chessboard);
} else {
for (int col = 0; col < chessboard.size(); ++col) {
if (checkPuts(chessboard, row, col)) {
chessboard[row].at(col) = 'Q';
NQueens(row + 1, chessboard, res);
chessboard[row].at(col) = '.';
}
}
}
}
vector<vector<string>> solveNQueens(int n) {
vector<vector<string> > res;
if (n <= 0)
return res;
vector<string> chessboard(n, string(n, '.'));
NQueens(0, chessboard, res);
return res;
}