【剑指offer】面试题13 机器人的运动范围

1.考点

  • 考点1:对于二维数组的遍历理解,其往往是个一维数组存储,将其理解为二维数组,那么在知道二维数组的行rows与列cols的情况下,任意的位置即为row*cols+col;
  • 考点2:试探回溯法在不同的寻路问题中的使用情况,比如本题其实主要是使用了深度优先的试探方法,其回溯过程其实并没有很明显的体现,主要就是在完成一个分支后return count值,而随着分支的不断结束而不断地进行下一个递归式子的过程其实就是回溯。
  • 考点3:BFS算法:广度优先搜索算法和深度优先搜索算法的本质不同在对于上下左右的走法处理上,其往往是通过不断地循环所要走的方向,然后通过队列来出队获取节点,而不是DFS的递归或栈。

2.代码

  • 总结了相关的试探回溯法解题思路如下:
  • (1)分析问题:问题往往分两种,一种是经典的一维数组/二维数组存储数据,一种是采用自定义的节点来实现存储过程,前者适合使用递归的方式来实现试探回溯,因为需要将源数据数组不断地调用;而后者没有源数据数组,所以适合使用栈存储的方式来实现试探回溯。不过后者也有个问题,即如何实现上下左右移动时如何保证每次式子中的数据就是原始的node点,而不是上一步移动后的node点。(以下都以递归情况开始写)
  • (2)确定起点与约束条件:起点可能是定死的比如(0,0),也有可能是遍历所有的点,也有可能是选择某些点,所以需要一些操作来先适应起点的选取(比如直接输入单点,或者通过循环不断地更换起点);约束条件则根据题目中了解到底有什么限制(比如坐标不能大于多少啦,路径要跟着给定的走啊之类的)
  • (3)试探回溯函数A:通过起点的选择与基本的前置条件确定(比如行列在规定值内),再写试探回溯函数A,其中A中往往需要传入主函数的所有参数,以及相关的行列位置。而进入A之后,往往要判断前置条件(因为会不断递归A函数所有还需要判断)与约束条件,如果可以的话则进入递归函数组(内部进行上下左右等操作),如果不可以的话进行回溯或返回值等操作;
  • (4)A中的多种特例:比如前置条件与约束条件的判断较为复杂,需要辅助函数check来实现,比如内部的上下左右移动不方便,需要别的函数来辅助之类的。
//仍然是经典的递归解法,在递归中回溯
class Solution 
{
public:
	//思想:试探回溯,函数分块实现
	int movingCount(int threshold, int rows, int cols)
	{
		if (threshold < 0 || rows < 0 || cols < 0)
			return 0;
		bool* isVisited = new bool[rows*cols];
		memset(isVisited, false, rows*cols);
		int count = movingCountByPoint(threshold, rows, cols, 0, 0, isVisited);

        delete[] isVisited;
		return count;
	}
    
    int movingCountByPoint(int threshold, int rows, int cols, int row, int col, bool* isVisited)
	{
		int count = 0;
		//如果判断能够对应的输入数值能够满足check条件(即能够进入此位置)
		if (check(threshold, rows, cols, row, col, isVisited))
		{
			//将对应的位置置为true,然后开始进行上下左右的试探与回溯,返回计数值(进入此位置的默认1+探测值)
			isVisited[row*cols + col] = true;
			count = 1 + movingCountByPoint(threshold, rows, cols, row + 1, col, isVisited)
				+ movingCountByPoint(threshold, rows, cols, row - 1, col, isVisited)
				+ movingCountByPoint(threshold, rows, cols, row, col + 1, isVisited)
				+ movingCountByPoint(threshold, rows, cols, row, col - 1, isVisited);
		}
		return count;
	}

    bool check(int threshold, int rows, int cols, int row, int col, bool* isVisited)
	{
		//前置条件判断,包括其数据正确性与是否被访问
		if (row >= 0 && row < rows && col >= 0 && col < cols && !isVisited[row*cols + col])
		{
			int sum = 0;
			while (row)
			{
				sum += row % 10;
				row /= 10;
			}
			while (col)
			{
				sum += col % 10;
				col /= 10;
			}
			return (sum <= threshold);
		}
		return false;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值