第18周 算法思想-搜索(BFS)

BFS

总结:BFS通常比较适用于寻找最短路径,这三道题都是采用的类似层次遍历的写法,这样就不用把路径长度信息存入节点信息中。

计算在网格中从原点到特定点的最短路径长度

注意点:

  • 不仅要检查出发点的有效性还要检查终止点的有效性
  • 路径长度计数变量+1的时机,也就是什么时候让路径长度+1
  • 记录visited是必须的
typedef pair<int,int> P;

class Solution {
public:
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        int n = grid.size();
        
        if(grid[0][0] == 1 || grid[n-1][n-1] == 1)
            return -1;
    
        int ans = 1;
        int dx[8] = {0,0,1,1,1,-1,-1,-1};
        int dy[8] = {1,-1,1,0,-1,1,0,-1};
        
        queue<P> q;
        q.push({0, 0});
        grid[0][0] = 2;
        
        while(!q.empty()){
            int size = q.size();
            
            while(size--){
                P u = q.front();
                q.pop();    
                
                if(u.first == n-1 && u.second == n-1)
                    return ans;
                
                for(int i = 0;i < 8; i++){
                    int nx = u.first + dx[i];
                    int ny = u.second + dy[i];
                    
                    if(nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 0 && grid[nx][ny] != 2){
                        grid[nx][ny] = 2;
                        q.push({nx, ny});
                    }
                }
            }
            
            ans += 1;
        }
        
        return -1;
    }
};

组成整数的最小平方数数量

本题最直观的解法是动态规划

class Solution {
public:
    int numSquares(int n) {
        int dp[10005];
        dp[0] = 0;
        
        for(int i = 1;i <= n; i++){
            dp[i] = 100005;
            for(int j = sqrt(i);j >= 1; j--)
                dp[i] = min(dp[i], dp[i-j*j] + 1);                
        }
        return dp[n];
    }
};

将1…n当作一个图中的节点,如果相差一个平方数则连一条边,这样就把平方数加和到n转换到了n到0的边的条数,用BFS求解

class Solution {
public:    
        int numSquares(int n){
            /*
            思路:1...n都是图中的节点,如果相差一个平方数则连一条边,这样就把平方数加和到n转换到了n到0的边的条数
            */
            int mark[10005];
            memset(mark, 0, sizeof(mark));
            
            queue<int> q;
            q.push(n);
            mark[n] = 1;
            
            int ans = 0;
            
            while(!q.empty()){
                int size = q.size();
                ans += 1;
                
                while(size--){
                    int u = q.front();
                    q.pop();
                    for(int v = sqrt(u);v >= 1; v--){
                        if(v*v == u)
                            return ans;
                        else if(v*v < u && mark[u-v*v] == 0){
                            q.push(u - v*v);
                            mark[u-v*v] = 1;
                        }
                    }
                }
            }
            return ans;
            
        }
};

最短单词路径

class Solution {
public:
    bool compare(string& s1, string& s2){
        if(s1.size() != s2.size())
            return false;
        int flag = 0;
        for(int i = 0;i < s1.size(); i++)
            if(s1[i] != s2[i]){
                if(flag == 0)
                    flag = 1;
                else if(flag == 1)
                    return false;
            }
        return true;
    }
    
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        
        int source, target = -1;
        
        int n = wordList.size();
        
        vector<int> G[5005];
        int visited[5005];
        memset(visited, 0, sizeof(visited));
        
        wordList.push_back(beginWord);
        source = n;
        
        for(int i = 0;i <= n; i++){
            for(int j = i+1; j <= n; j++){
                if(compare(wordList[i], wordList[j])){
                    G[i].push_back(j);
                    G[j].push_back(i);
                }
            }
            if(wordList[i] == endWord)
                target = i;
        }
        
        if(target == -1)
            return 0;
        
        queue<int> q;
        q.push(source);
        visited[source] = 1;
        
        int ans = 0;
        
        while(!q.empty()){
            int size = q.size();
            
            ans += 1;
            
            while(size--){
                int u = q.front();
                q.pop();
                visited[u] = 1;
                
                if(u == target)
                    return ans;
                
                for(int i = 0;i < G[u].size(); i++){
                    int v = G[u][i];
                    if(visited[v] == 0)
                        q.push(v);
                }
            }
        }
        
        return 0;
            
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值