【算法】【搜索和回溯】Leetcode高频面试题

BFS

完全平方数

题目链接:https://leetcode-cn.com/problems/perfect-squares/

class Solution {
public:
    int numSquares(int n) {
        int max_sqrt = floor(sqrt(n));
        queue<int> q;
        q.push(0);

        int res = 0;

        while(!q.empty())
        {
            int len = q.size();
            res++;
            for(int i = 0; i < len; i++)
            {
                int val = q.front();
                q.pop();
                for(int j = max_sqrt; j >= 0 ; j--)
                {
                    int sum = val + j * j;
                    if(sum == n) return res;
                    if(sum > n) continue;
                    q.push(sum);
                }
            }
        }
        return -1;
    }
};

岛屿数量

题目链接:https://leetcode-cn.com/problems/number-of-islands/

class Solution {
public:
    int res = 0;
    int numIslands(vector<vector<char>>& grid) {
        if(grid.empty()) return 0;
        int n = grid.size(), m = grid[0].size();
        vector<vector<bool>> flag(n, vector<bool>(m, false));

        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                if(!flag[i][j] && grid[i][j] == '1')
                {
                    bfs(grid, flag, i, j);
                    res++;
                }
            }
        }
        return res;
    }

    void bfs(vector<vector<char>>& grid, vector<vector<bool>>& flag, int i, int j)
    {
        queue<pair<int, int>> q;
        q.push({i, j});
        int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};

        flag[i][j] = true;
        while(!q.empty())
        {
            auto tmp = q.front();
            q.pop();
            
            for(int i = 0; i < 4; i++)
            {
                int new_x = tmp.first + dx[i], new_y = tmp.second + dy[i];
                if(new_x < 0 || new_x >= grid.size() || new_y < 0 || new_y >= grid[0].size()) continue;
                if(!flag[new_x][new_y] && grid[new_x][new_y] == '1') 
                {
                    q.push({new_x, new_y});
                    flag[new_x][new_y] = true;
                }

            }
        }

    }
};

被围绕的区域

题目链接: https://leetcode-cn.com/problems/surrounded-regions/

class Solution {
public:
    void solve(vector<vector<char>>& board) {
        if(board.empty()) return ;
        int n = board.size(), m = board[0].size();


        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                if((i == 0 || j == 0 || i == n - 1 || j == m - 1) && board[i][j] == 'O')
                {
                    bfs(board, i, j);
                }
        for(int i = 0; i < n ; i++)
        {
            for(int j = 0; j < m ; j++)
            {
                if(board[i][j] == 'O') board[i][j] = 'X';
                if(board[i][j] == '#') board[i][j] = 'O';
            }
        }
    }

    void bfs(vector<vector<char>>& board, int x, int y)
    {
        queue<pair<int, int>> q;
        q.push({x, y});
        board[x][y] = '#';

        while(!q.empty())
        {
            auto tmp = q.front();
            q.pop();    
            x = tmp.first, y = tmp.second;
            int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
            for(int i = 0; i < 4; i++)
            {
                int new_x = x + dx[i], new_y = y + dy[i];
                if(new_x < 0 || new_x >= board.size() || new_y < 0 || new_y >= board[0].size())
                    continue;
                char ch = board[new_x][new_y];
                
                if(ch == 'O')
                {   
                    board[new_x][new_y] = '#';
                    q.push({new_x, new_y});
                }
            }
        }
    }
};

DFS

电话号码的字母组合

题目链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/

class Solution {
public:
    unordered_map<char, string> hashmap;
    vector<string> res;
    string path;
    vector<string> letterCombinations(string digits) 
    {
        if(digits.empty()) return {};
        digits2map();
        dfs(digits, 0);
        return res;

    }
    void dfs(string digits, int u)
    {
        if(u == digits.size()) 
        {
            res.push_back(path);
            return ;
        }

        char ch = digits[u];
        string str = hashmap[ch];

        for(auto ch : str)
        {
            path += ch;
            dfs(digits, u + 1);
            path.pop_back();
        }
    }



    void digits2map()
    {
        hashmap['2'] = "abc";
        hashmap['3'] = "def";
        hashmap['4'] = "ghi";
        hashmap['5'] = "jkl";
        hashmap['6'] = "mno";
        hashmap['7'] = "pqrs";
        hashmap['8'] = "tuv";
        hashmap['9'] = "wxyz";
    }
};

零钱兑换

题目链接:https://leetcode-cn.com/problems/coin-change/

class Solution {
public:
    int res = INT_MAX;
    int coinChange(vector<int>& coins, int amount) {
        sort(coins.rbegin(), coins.rend());
        int u = 0;
        dfs(coins, 0, amount, u, 0);
        return res == INT_MAX ? -1 : res;
    }

    void dfs(vector<int>& coins, int sum, int amount, int u, int cnt)
    {
        if(sum == amount) 
        {
            res = min(res, cnt);
            return ;
        }
        if(u == coins.size()) return ;

        int target = amount - sum;

        for(int i = target / coins[u];  i >= 0 && i + cnt < res; i--)
        {
            dfs(coins, sum + coins[u] * i, amount, u + 1, cnt + i);
        }
    }
};

打家劫舍III

题目链接:https://leetcode-cn.com/problems/house-robber-iii/

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    int rob(TreeNode* root) {
        if(!root) return 0;

        auto res = dfs(root);
        //1. 包含当前根节点
        //2. 不包含当前根节点
        return max(res.first, res.second);

    }

    pair<int, int> dfs(TreeNode* root)
    {
        if(!root) return {0, 0};

        pair<int, int> res(0, 0);
        
        pair<int, int> l = dfs(root -> left);
        pair<int, int> r = dfs(root -> right);

        //包含根节点,有左右节点
        res.first = l.second + r.second + root -> val;
        //不包含根节点,有左右节点
        //左1 + 右1; 左1 + 右2;左2 + 右1; 左2 + 右2;
        res.second = max(l.first, l.second) + max(r.first, r.second);
        return res;
    }
};

火柴拼正方形

题目链接:https://leetcode-cn.com/problems/matchsticks-to-square/

class Solution {
public:
    bool makesquare(vector<int>& nums) {
        //小于4时返回假
        if(nums.size() < 4) return false;
        //累加求和
        int sum = 0;
        for(int i = 0; i < nums.size(); i++)
            sum += nums[i];
        //和不能被4整除肯定不能拼成正方形
        if(sum % 4) return false;
        
        //从大到到小排序
        sort(nums.rbegin(), nums.rend());

        int bucket[4] = {0};
        return dfs(0, nums, sum / 4, bucket);
    }
    //搜索n次,n为元素个数,每次搜索每个桶中应该放的数
    bool dfs(int u, vector<int>& nums, int target, int bucket[])
    {
        if(u >= nums.size())
        {
            for(int i = 0; i < 4; i++)
                if(bucket[i] != target) return false;
            return true;
        }

        for(int i = 0; i < 4; i++)
        {
            if(bucket[i] + nums[u] > target) continue;
            bucket[i] += nums[u];
            if(dfs(u + 1, nums, target, bucket)) return true;
            bucket[i] -= nums[u];
        }
        return false;
    }

};

括号生成

class Solution {
public: 
    
    void dfs(vector<string>& res, string& path, int l, int r, int n)
    {
        if( l == n && r == n) 
        {
            res.push_back(path);
            return;
        }

        //剪枝
        if(l < r) return;

        if(l < n) 
        {
            string tmp = path + "(";
            dfs(res, tmp, l + 1, r, n);
        }
        if(r < n)
        {
            string tmp = path + ")";
            dfs(res, tmp, l, r + 1, n);
        }
    }
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        string str = "";
        dfs(res, str, 0, 0, n);
        return res;
    }
};
posted @ 2020-08-17 10:31  NaughtyCoder  阅读(122)  评论(0)    收藏  举报