数据结构与算法:宽度优先遍历

前言

进入图论部分难度明显提升了一大截,思路想不到一点……

一、宽度优先遍历

1.内容

宽度优先遍历主要用于在图上求最短路。

(1)特点

宽度优先遍历的特点就是逐层扩展,最短路即层数

(2)使用条件

无向图且任意节点间距离相等

(3)注意

进入队列后需标记状态防止重复入队。

可剪枝!!可单源头可多源头!!

(4)难点

主要难点在于节点如何找路、路的展开以及剪枝方法。

2.题目

(1)地图分析
class Solution {
public:

    //移动 -> 上下左右
    vector<int>move={-1,0,1,0,-1};

    int maxDistance(vector<vector<int>>& grid) {
        int n=grid.size();

        vector<vector<bool>>visited(n,vector<bool>(n));
        queue<pair<int,int>>node;
        int seas=0;

        //初始化
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(grid[i][j]==1)//陆地
                {
                    visited[i][j]=true;
                    node.push(make_pair(i,j));
                }
                else//海洋
                {
                    seas++;
                }
            }
        }

        //特例
        if(seas==0||seas==n*n)
        {
            return -1;
        }

        //统计
        int level=0;
        while(!node.empty())
        {
            level++;
            int size=node.size();
            for(int i=0,x,y,nx,ny;i<size;i++)
            {
                x=node.front().first;
                y=node.front().second;
                node.pop();
                for(int j=0;j<4;j++)
                //j=0:上
                //j=1:下
                //j=2:左
                //j=3:右
                {
                    nx=x+move[j];
                    ny=y+move[j+1];
                    if(nx>=0&&nx<n&&ny>=0&&ny<n&&grid[nx][ny]==0&&!visited[nx][ny])
                    {
                        visited[nx][ny]=true;
                        node.push(make_pair(nx,ny));
                    } 
                }
            }
        }

        return level-1;//到最后还被多加了一次
    }
};

这个题主要是引入节点向周围找路的方法。

整体思路就是从每个陆地往外进行宽度优先遍历,遇到海就“感染”入队,最后返回层数-1即可。

首先,要遍历每个陆地入队,与此同时还可以顺便统计海洋数量。若全为海或者全为陆地就直接返回。之后进行宽度优先遍历统计level层数,每次从队列里取队列的size个,即当前层的所有节点,然后每个节点向外扩。注意这里向外扩的写法,设置move数组为-1,0,1,0,-1,之后每来到一个位置就让下一步的nx=x+move[j],ny=y+move[j+1],这样就能实现向上下左右四个方向扩。当下一步的位置有效时,就记录状态然后入队。

(2)贴纸拼词
class Solution {
public:

    //邻接表建图
    vector<vector<string>>graph;

    int minStickers(vector<string>& stickers, string target) {
        int n=stickers.size();
        graph.resize(26);//能消目标某字母的字符串

        //路的展开 -> 用每个贴纸会导致不同的剩余情况

        for(int i=0;i<n;i++)
        {
            //排序字符串 -> 只考虑词频和字母
            sort(stickers[i].begin(),stickers[i].end());

            //建图
            for(int j=0;j<stickers[i].length();j++)
            {
                //统计能消的字符
                if(j==0||stickers[i][j]!=stickers[i][j-1])//不重复加
                {
                    graph[stickers[i][j]-'a'].push_back(stickers[i]);
                }
            }
        }

        //排序
        sort(target.begin(),target.end());

        set<string>visited;//剩余字符串去重
        queue<string>node;
        visited.insert(target);
        node.push(target);
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值