品牌網(wǎng)站建設(shè)還來(lái)大蝌蚪開(kāi)發(fā)新客戶的十大渠道
面試題13. 機(jī)器人的運(yùn)動(dòng)范圍
難度:middle\color{orange}{middle}middle
題目描述
地上有一個(gè) mmm 行 nnn 列的方格,從坐標(biāo) [0,0][0,0][0,0] 到坐標(biāo) [m?1,n?1][m-1,n-1][m?1,n?1] 。一個(gè)機(jī)器人從坐標(biāo) [0,0][0, 0][0,0] 的格子開(kāi)始移動(dòng),它每次可以向左、右、上、下移動(dòng)一格(不能移動(dòng)到方格外),也不能進(jìn)入行坐標(biāo)和列坐標(biāo)的數(shù)位之和大于 kkk 的格子。例如,當(dāng) kkk 為 18
時(shí),機(jī)器人能夠進(jìn)入方格 [35, 37] ,因?yàn)?3+5+3+7=18
。但它不能進(jìn)入方格 [35, 38],因?yàn)?3+5+3+8=19
。請(qǐng)問(wèn)該機(jī)器人能夠到達(dá)多少個(gè)格子?
示例 1:
輸入:m = 2, n = 3, k = 1
輸出:3
示例 2:
輸入:m = 3, n = 1, k = 0
輸出:1
提示:
- 1<=n,m<=1001 <= n,m <= 1001<=n,m<=100
- 0<=k<=200 <= k <= 200<=k<=20
算法
(BFS)
這是一個(gè)典型的寬度優(yōu)先搜索問(wèn)題,我們從 (0, 0)
點(diǎn)開(kāi)始,每次朝上下左右四個(gè)方向擴(kuò)展新的節(jié)點(diǎn)即可。
擴(kuò)展時(shí)需要注意新的節(jié)點(diǎn)需要滿足如下條件:
- 之前沒(méi)有遍歷過(guò),這個(gè)可以用一個(gè)
bool
數(shù)組來(lái)判斷; - 沒(méi)有走出邊界;
- 橫縱坐標(biāo)的各位數(shù)字之和小于
k
最后答案就是所有遍歷過(guò)的合法的節(jié)點(diǎn)個(gè)數(shù)。
復(fù)雜度分析
-
時(shí)間復(fù)雜度:每個(gè)節(jié)點(diǎn)最多只會(huì)入隊(duì)一次,所以時(shí)間復(fù)雜度不會(huì)超過(guò)方格中的節(jié)點(diǎn)個(gè)數(shù)。最壞情況下會(huì)遍歷方格中的所有點(diǎn),所以時(shí)間復(fù)雜度就是 O(nm)O(nm)O(nm)
-
空間復(fù)雜度 : O(n)O(n)O(n)
C++ 代碼
class Solution {
public:// 求單個(gè)數(shù)字的各個(gè)位數(shù)之和int get_single_num(int x) {int s = 0;while (x) {s += x % 10;x /= 10;}return s;}//求一個(gè)方格的坐標(biāo)位數(shù)之和int get_sum(pair<int, int> p) {return get_single_num(p.first) + get_single_num(p.second);}int movingCount(int m, int n, int k) {//m 行 n 列 threshhold -> kif (!k) return 1;if (!m || !n) return 0;int res = 0;vector<vector<bool>> st(m, vector<bool>(n));queue<pair<int, int>> q;q.push({0, 0});int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};while (q.size()) {auto t = q.front();q.pop();if (get_sum(t) > k || st[t.first][t.second]) continue;res ++;st[t.first][t.second] = true;for (int i = 0; i < 4; i ++) {int x = t.first + dx[i], y = t.second + dy[i];if (x >= 0 && x < m && y >= 0 && y < n)q.push({x, y});}}return res;}
};