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;
}    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值