インタビューの質問13-ロボットの可動範囲

インタビューの質問13-ロボットの可動範囲

タイトルの説明

座標[0,0]から座標[m-1、n-1]まで、地面にm行n列のグリッドがあります。ロボットは座標[0、0]のグリッドから開始し、一度に1つのグリッドを左、右、上、下に移動できます(グリッドの外に移動できません)。また、行と列の座標を入力できません。数字の合計は、 kの格子。たとえば、kが18の場合、3 + 5 + 3 + 7 = 18であるため、ロボットは正方形[35、37]に入ることができます。しかし、3 + 5 + 3 + 8 = 19であるため、正方形[35、38]に入ることができません。ロボットが到達できるグリッドはいくつですか?

示例 1:
输入:m = 2, n = 3, k = 1
输出:3

示例 2:
输入:m = 3, n = 1, k = 0
输出:1
提示:

1 <= n,m <= 100
0 <= k <= 20

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

この主題は79-WordSearchそれよりはるかに単純です。対象要件は要件を満たすグリッドの合計数。つまり、各グリッドは複数回歩くことができます。この質問では、BFSがDFSよりも適しています。このようにして、問題を直感的に解決できます。

原点(0,0)から始まり、合計がK未満である限り、Trueとしてマークされます。最後に、mxn行列全体をトラバースし、すべてTrueの数値を計算するだけです。

79-WordSearchパスを見つけるのは問題なので、ステータスをマークするだけでなく、バ​​ックトラックしてステータスをリセットする必要もあります。

解決策

class Solution:
	directions = [(0,-1),(-1,0),(0,1),(1,0)]
	def movingCount(self, m: int, n: int, k: int) -> int:
		marked = [[False  for _ in  range(n)] for _ in  range(m)]
		self.__move(0, 0, marked, m, n, k)
		result = 0
		for i in  range(m):
			for j in  range(n):
				if marked[i][j] == True:
					result += 1
		return result

	def __move(self,start_x, start_y, marked, m, n, k):
		str_start = str(start_x) + str(start_y)
		sum_start = 0
		for i in  range(len(str_start)):
			sum_start += int(str_start[i])
		if sum_start <= k:
			marked[start_x][start_y] = True
			# examine next point
			for direction in  self.directions:
				new_x = start_x + direction[0]
				new_y = start_y + direction[1]
				if  0<= new_x <m and  0<= new_y <n and \
					not marked[new_x][new_y]:
					self.__move(new_x, new_y, marked, m, n, k)

現在のノード(start_x, start_y)が要件を満たしている場合、それに基づいて、周囲の4方向の隣接ノードが要件を満たしているかどうかを調べます。要件を満たすポイントが見つかった場合は、隣接ノードのチェックを続けます。これがイテレーションです

最適化

数値の合計を計算する方法は?

log xがxの桁数を知るために、残りの10をとるだけでよいので、xを10で割ります。この操作は、xの10進数を右に1シフトすることと同じです。桁数(バイナリの>>右シフト演算子に似ています)。xが0で終わるまで繰り返します。

非表示の最適化

検索中に、検索方向を上下にではなく、右および下に減らすことができますこの答え、増幅のk個の制約にマップ* 16 16を示し、トレンド可能正方形グリッドの各列の座標及びデジタル和の列座標の値、非ブルー市松の代表障害グリッド。つまり、その値は現在の制限条件k以下です。
制約kが増加するにつれて、(0、0)が配置されている青い正方形の領域に新しく追加された、遮られていない正方形が、上部または左側の正方形を1ステップ移動することによって取得できることがわかります。
他の接続されていない青いグリッド領域はkの増加に関連しており、接続は上または左のグリッドを1ステップ移動することによっても得られるため、検索方向を右または左に減らすことができます。次。

以下に示す参照コードが使用されqueueます。これはキューです。主要ありますqueue.put()し、queue.get()方法は。解決策は、要件を満たすノード
s保存するためのセットを設定し、判定対象のノードを保存するためのキューを設定することです。最後sに、セット内の数を計算することにより、要件を満たす数が得られます。

一般的に、BFS検索の問題は、キューの方法で解決されます。

def digitsum(n):
    ans = 0
    while n:
        ans += n % 10
        n //= 10
    return ans

class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:
        from queue import Queue
        q = Queue()
        q.put((0, 0))
        s = set()
        while not q.empty():
            x, y = q.get()
            if (x, y) not in s and 0 <= x < m and 0 <= y < n and digitsum(x) + digitsum(y) <= k:
                s.add((x, y))
                for nx, ny in [(x + 1, y), (x, y + 1)]:
                    q.put((nx, ny))
        return len(s)

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

この方法は、独自の方法よりも効率的ではありませんもちろん、上記の2つの最適化方法は、独自のコードを最適化するのに最適です。

再帰的方法

検索方向を下または右にするだけでよいことを考えると、再帰的解法を導出できます。

座標が到達可能かどうかとして定義さvis[i][j](i, j)、到達可能であれば1を返し、そうでなければ0を返します。

まず、(i、j)がアクセス可能である必要があるため、iとjの数字の合計がkよりも大きいかどうかを判別し、大きい場合は直接vis[i][j]到達不能に設定する必要があります。

それ以外の場合、上記の検索方向は下または右である必要があるだけなので、(i、j)のグリッドは、(境界に関係なく)(i-1、j)または(i、j-1)の2つのグリッドからのみ取得されます。条件)の場合、vis[i][j]到達可能性の状態は次の式で計算できます。

\(\ textit {vis} [i] [j] = \ textit {vis} [i-1] [j] \ \ textrm {or} \ \ textit {vis} [i] [j-1] \)

つまり、1つのグリッドに到達できる限り、(i、j)このグリッドに到達可能です。したがって、すべてのグリッドをトラバースし、それらが到達可能かどうかを再帰的に計算し、変数ansを使用して到達可能なグリッドの数を記録するだけで済みます。

初期条件vis[i][j] = 1、再帰計算中の境界の処理に注意してください。

def digitsum(n):
    ans = 0
    while n:
        ans += n % 10
        n //= 10
    return ans

class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:
        vis = set([(0, 0)])
        for i in range(m):
            for j in range(n):
                if ((i - 1, j) in vis or (i, j - 1) in vis) and \
	                digitsum(i) + digitsum(j) <= k:
                    vis.add((i, j))
        return len(vis)

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

この方法の効率は、独自のコードの効率に似ています。

おすすめ

転載: www.cnblogs.com/rongyupan/p/12681754.html