leetcode面试题13:机器人的运动范围

此题依旧采用暴力法&BFS两种方法。

首先要看懂题目,例如如 let m = 20, n = 15, k = 9,下图绿色的代表能走的,红色的代表超过个位数的sum。图源于此
在这里插入图片描述
但题目是有限制的,“每次可以向左、右、上、下移动一格(不能移动到方格外)”,意思是右下角那一块绿色没办法走到(机器人不可能穿墙)。
在这里插入图片描述
我们首先使用暴力求解,思路:从左到右,从上到下遍历,判断当前位置的左边和上边机器人是否可以走到,如果走得到,则说明当前的位置也可以走得到。

int movingCount(int m, int n, int k) {
    int m_num=0,n_num=0;
    int res = 1;
    int flag[m][n];
    memset(flag,0,sizeof(flag));
    flag[0][0] = 1;
    for(int i = 0; i < m; i ++)
    {
        m_num = i/10+i%10;
        if(m_num > k) {
            continue;
        }
        for(int j = 0; j < n; j++)
        {
            n_num = j/10+j%10;
            if(  ((j>0 && flag[i][j-1] == 1) ||
                 (i> 0 && flag[i-1][j] == 1) )
                  && (m_num+n_num <=k))
            {
                res++;
                flag[i][j] = 1;
            }
        }
    }
    return res;

除了使用暴力法,我们还可以使用BFS,也就是广度优先遍历,之前写腐烂的橘子写过,但又忘了,这种题型刷的太少,又来发现原来是有模板的!广度优先遍历的原理咱就不说了,上一个注释版本的demo。

上面暴力法是通过判断当前位置的左边和上面是否能走,从而来判断当前位置是否能走,而BFS则是向下搜索,所以只需要搜索当前位置的下面和右边的位置是否能走到。刚好相反。

//得到当前位置个数之和
int indexsum(int num_i, int num_j)
    {
        int sum = 0;
        while(num_i !=0)
        {
            sum+= num_i%10 ;
            num_i /= 10;
        }
            while(num_j !=0)
        {
            sum+= num_j%10 ;
            num_j/= 10;
        }
        return sum;
    }
int movingCount(int m, int n, int k) {
    //广度优先遍历
    //定义下面和右边两个方向 
   int direction[2][2]={{0, 1}, {1, 0}};
    vector<vector<int>> visited(m,vector<int>(n,0));	//存放当前值是否能走,能走置1
    queue<pair<int,int>> q;	//队列,存放坐标
    q.push({0,0});    //原点入队
    int res = 0;	//存放结果
    visited[0][0] = 1;	//原点是一定可以走的
    //BFS算法
    while(!q.empty())
    {
        auto front = q.front(); 	//先获得队列的值
        q.pop();	//把这个值去掉
        int x = front.first; 	//得到当前位置
        int y = front.second;
        res+=1;		//能走的数+1
		//遍历两个方向
        for(int i = 0 ; i < 2; i ++)
        {
            int new_x = x + direction[i][0];		//得到新坐标
            int new_y = y + direction[i][1];
            //如果新坐标超出范围或不满足要求,则continue,意思是这个分支没有下一个结点了。
            if(new_x < 0 || new_x >= m || new_y < 0 || new_y >=n || visited[new_x][new_y] == 1 || indexsum(new_x,new_y) > k )
           {
               continue;
          }
          //如果满足要求,则说明可以搜索到,那么入队。
        q.push({new_x, new_y});
        //同时把这个点标记为能走。
        visited[new_x][new_y] = 1 ;
        }
    }
    //全部节点走完  
    return res;
}

那么,这个模板是什么呢?

当不需要确定当前遍历到哪一层:

while queue 不空:
    cur = queue.pop()
    for 节点 in cur的所有相邻节点:
        if 该节点有效且未访问过:
            queue.push(该节点)
作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/bfsmo-ban-yi-ci-bei-hui-chu-chu-shi-yong-by-fuxuem/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

当需要确定当前遍历到哪一层:

level = 0
while queue 不空:
    size = queue.size()
    while (size --) {
        cur = queue.pop()
        for 节点 in cur的所有相邻节点:
            if 该节点有效且未被访问过:
                queue.push(该节点)
    }
    level ++;

作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/bfsmo-ban-yi-ci-bei-hui-chu-chu-shi-yong-by-fuxuem/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

上面的BFS就是通过第一个模板写的,并且对原作者所写进行了优化。

https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/da-lao-jiu-shi-da-lao-zi-ji-xiang-po-nao-dai-du-xi/

https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/bfsmo-ban-yi-ci-bei-hui-chu-chu-shi-yong-by-fuxuem/

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值