十分钟总结一下今晚(力扣13)

今晚主要熟悉了DFS BFS 在一道题目里面的具体实现:
在这里插入图片描述
在这里插入图片描述
这道题目有两种方法:

DFS depth first search 深度优先搜索

DFS
采用递归的思想,直到找到最后一个满足条件的坐标,然后往回回溯;
一般来讲,就是定义自己的dfs函数,它的返回值就是满足条件的坐标个数;例如在本题里面,我需要找出机器人可以到达的所有格子总数,也就是满足条件的坐标总数。

我可以定义一个dfs函数 ,它的返回值就是满足条件的坐标总数:

 int movingCount(int m, int n, int k) {
        return dfs(0,0,0,0,m,n,k);
    }

然后,在dfs的具体实现中,当满足条件的时候,我返回1+dfs(向下一格)+dfs(向右一格)

int dfs(int i,int j,int si,int sj,int m,int n,int k){
        return 1+dfs(i+1,j,(i+1)%10==0? si-8:si+1,sj,m,n,k)+dfs(i,j+1,si,(j+1)%10==0? sj-8:sj+1,m,n,k);
    }

什么时候满足条件呢?
索引i j 需要满足m和n的约束 ;
坐标各位数之和需要满足k的约束;

 int dfs(int i,int j,int si,int sj,int m,int n,int k,vector<vector<bool>>& visited){
        if(i>=m||j>=n||(si+sj)>k) return 0;
        return 1+dfs(i+1,j,(i+1)%10==0? si-8:si+1,sj,m,n,k)+dfs(i,j+1,si,(j+1)%10==0? sj-8:sj+1,m,n,k);
    }

所以,一旦不满足这些条件,我就直接返回0;

至此,大概的思路我们有了,但是仔细一想(想个屁,跑测试出错了!)会有坐标被重复访问,因此我们需要添加一个额外的判断,如果该坐标已经访问过了,那么就return 0;
所以,我们 修改 主函数:采用一个二维的bool数组来存储元素被访问的情况,如果访问过,就置为true;

int movingCount(int m, int n, int k) {
        //DFS 深度优先搜索 从底部开始
        //使用递归,往底部深入,直到最后一个元素
        vector<vector<bool>> visited(m,vector<bool>(n,0));
        return dfs(0,0,0,0,m,n,k,visited);
    }

那么,如果该坐标为true,就return 0;因此,修改dfs:

int dfs(int i,int j,int si,int sj,int m,int n,int k,vector<vector<bool>>& visited){
        if(i>=m||j>=n||(si+sj)>k||visited[i][j]) return 0;
        visited[i][j]=true;
        return 1+dfs(i+1,j,(i+1)%10==0? si-8:si+1,sj,m,n,k,visited)+dfs(i,j+1,si,(j+1)%10==0? sj-8:sj+1,m,n,k,visited);
    }

在这里插入图片描述

BFS breath first search 广度优先搜索

2. BFS
BFS 的思想是使用队列来实现,也就是先进先出,从头部位置的格子坐标开始判断,具体来说就是:

首先,人为规定,向下方向>向右方向
在这里插入图片描述
还是这个图,那么判断的格子顺序就是:
(0,0)
(1,0)
(0,1)
(2,0)
(1,1)
(0,2)
(3,0)
(2,1)
(1,2)
(0,3)
(3,1)
(2,2)
(1,3)
(3,2)
(2,3)
(3,3)
我们每次从队列的头部吐出一个数据,如果满足条件,格子数+1,并且在尾巴上压入向下、向右方向的元素;
可以使用一个vector存储(i , j , si , sj)
判断的时候,判断条件和上面DFS一样,

if(i>=m||j>=n||(si+sj)>k) 不满足;
int movingCount(int m, int n, int k) {  
        queue<vector<int> > pos ;
        pos.push({0,0,0,0});
        int res=0;
        while(pos.size()>0){
            vector<int> tmpArray=pos.front();
            pos.pop();
            int i=tmpArray[0],j=tmpArray[1],si=tmpArray[2],sj=tmpArray[3];
            if(i>=m||j>=n||(si+sj)>k) continue;
            res++;
            pos.push({i+1,j,(i+1)%10==0 ? si-8:si+1,sj});
            pos.push({i,j+1,si,(j+1)%10==0 ? sj-8:sj+1});

        }
        return res;
    }

同样的 也有元素重复访问的情况,因此,也需要一个二维bool数组存储被访问的情况;
于是,代码可以修改为:

int movingCount(int m, int n, int k) {
        //深度优先搜索DFS(栈的思想,从底部开始计数) 与 广度优先搜索BFS(队列的思想,从顶部开始计数)
        //1. 首先是采用BFS实现 
        //从坐标(0,0)开始往下遍历,顺序的往队列里面push元素,如果遇到了不满足的坐标,就直接continue,后面的向下向右push直接跳过;push的是坐标(i,j,si,sj)

        vector<vector<bool>> visited (m,vector<bool> (n,0));//用于存储已经访问过的元素,true false 
        queue<vector<int> > pos ;
        pos.push({0,0,0,0});
        int res=0;
        while(pos.size()>0){
            vector<int> tmpArray=pos.front();
            pos.pop();

            int i=tmpArray[0],j=tmpArray[1],si=tmpArray[2],sj=tmpArray[3];
            if(i>=m||j>=n||(si+sj)>k||visited[i][j]) continue;
            visited[i][j]=true;
            res++;
            pos.push({i+1,j,(i+1)%10==0 ? si-8:si+1,sj});
            pos.push({i,j+1,si,(j+1)%10==0 ? sj-8:sj+1});

        }
        return res;
    }

结尾:使用的时间远不止十分钟,但是很爽啊,现在的我思路顺畅,无欲无求!!!晚安

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值