日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【四重优化,速看】剑指 Offer 13. 机器人的运动范围

發(fā)布時(shí)間:2024/2/28 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【四重优化,速看】剑指 Offer 13. 机器人的运动范围 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

立志用最少的代碼做最高效的表達(dá)


題目

地上有一個(gè)m行n列的方格,從坐標(biāo) [0,0] 到坐標(biāo) [m-1,n-1] 。一個(gè)機(jī)器人從坐標(biāo) [0, 0] 的格子開(kāi)始移動(dòng),它每次可以向左、右、上、下移動(dòng)一格(不能移動(dòng)到方格外),也不能進(jìn)入行坐標(biāo)和列坐標(biāo)的數(shù)位之和大于k的格子。例如,當(dāng)k為18時(shí),機(jī)器人能夠進(jìn)入方格 [35, 37] ,因?yàn)?+5+3+7=18。但它不能進(jìn)入方格 [35, 38],因?yàn)?+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 <= 100
0 <= k <= 20


文章目錄

  • 題目
  • 第一次解題
  • 第二次解題
  • 第三次優(yōu)化
  • 第四次優(yōu)化
  • 完整可運(yùn)行代碼


第一次解題

錯(cuò)誤解法:直接遍歷二維數(shù)組試圖解題,發(fā)現(xiàn)出錯(cuò),因?yàn)闄C(jī)器人無(wú)法越過(guò)障礙

class Solution {public int movingCount(int m, int n, int k) {int num1, num2, sum = 0;for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {num1 = 0; num2 = 0;int ii = i, jj = j;while(ii != 0) { num1 += ii%10; ii/= 10; }while(jj != 0) { num2 += jj%10; jj/= 10; }if(num1 + num2 <= k) sum++;System.out.println(i + " " + j + " " + num1 + " " + num2 + " " + sum);}}return sum;} }

第二次解題

仔細(xì)思考后發(fā)現(xiàn),這是一道考查連通塊的題,即連通(0,0)的點(diǎn)的個(gè)數(shù)。
于是用DFS解,如下:

static class Solution {boolean[][] vis;int sum;int kk; // 代替k,定義全局變量,可以為dfs方法減少一個(gè)參數(shù)int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局變量的定義vis = new boolean[m][n];sum = 1; // (0,0)一定能被訪問(wèn)到kk = k; mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 終止條件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、超界, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn) continue;// 2、被訪問(wèn)過(guò),continueif(vis[xx][yy]) continue;// 3、計(jì)算是否能到達(dá)int xx1 = xx, yy1 = yy;int num1 = 0, num2 = 0;while(xx1 != 0) { num1 += xx1%10; xx1 /= 10; }while(yy1 != 0) { num2 += yy1%10; yy1 /= 10; }if(num1 + num2 <= kk) { // 符合vis[xx][yy] = true;sum++;dfs(xx, yy);}}} }

第三次優(yōu)化

解法2中考慮了m或n是100的情況,但即使m or n為100,k最大值也只能取到20,因此不滿足條件。 因此只需考慮m or n是二位數(shù)的情況即可。

class Solution {boolean[][] vis;int sum;int kk; // 代替k,定義全局變量,可以為dfs方法減少一個(gè)參數(shù)int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局變量的定義vis = new boolean[m][n];sum = 1; // (0,0)一定能被訪問(wèn)到kk = k; mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 終止條件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否滿足條件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾經(jīng)走過(guò)這個(gè)點(diǎn)if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}} }

第四次優(yōu)化

第三次優(yōu)化中,考慮的機(jī)器人從上下左右四個(gè)方向走的問(wèn)題,但仔細(xì)思考后發(fā)現(xiàn):
由于從0,0開(kāi)始,因此只考慮向右or向下走即可。

class Solution {boolean[][] vis;int sum;int kk; // 代替k,定義全局變量,可以為dfs方法減少一個(gè)參數(shù)int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局變量的定義vis = new boolean[m][n];sum = 1; // (0,0)一定能被訪問(wèn)到kk = k; mm = m; nn = n;next = new int[][]{{1,0}, {0,1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 終止條件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 2; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否滿足條件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾經(jīng)走過(guò)這個(gè)點(diǎn)if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}} }

完整可運(yùn)行代碼

最后附上完整可運(yùn)行代碼

public class 劍指Offer13_機(jī)器人的運(yùn)動(dòng)范圍 {// 錯(cuò)誤解法: 因?yàn)闊o(wú)法越過(guò)障礙static class Solution_1 {public int movingCount(int m, int n, int k) {int num1, num2, sum = 0;for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {num1 = 0; num2 = 0;int ii = i, jj = j;while(ii != 0) { num1 += ii%10; ii/= 10; }while(jj != 0) { num2 += jj%10; jj/= 10; }if(num1 + num2 <= k) sum++;System.out.println(i + " " + j + " " + num1 + " " + num2 + " " + sum);}}return sum;}}// 解法2:dfs:本質(zhì)上是求連通塊,就是連通(0,0)點(diǎn)的所有點(diǎn)的個(gè)數(shù)Sstatic class Solution_2 {boolean[][] vis;int sum;int kk; // 代替k,定義全局變量,可以為dfs方法減少一個(gè)參數(shù)int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局變量的定義vis = new boolean[m][n];sum = 1; // (0,0)一定能被訪問(wèn)到kk = k; mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 終止條件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、超界, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn) continue;// 2、被訪問(wèn)過(guò),continueif(vis[xx][yy]) continue;// 3、計(jì)算是否能到達(dá)int xx1 = xx, yy1 = yy;int num1 = 0, num2 = 0;while(xx1 != 0) { num1 += xx1%10; xx1 /= 10; }while(yy1 != 0) { num2 += yy1%10; yy1 /= 10; }if(num1 + num2 <= kk) { // 符合vis[xx][yy] = true;sum++;dfs(xx, yy);}}}}// 解法2中考慮的m或n是100的情況,但即使m or n為100,k最大值也只能取到20,因此不滿足條件。 因此只需考慮m or n是二位數(shù)的情況即可。static class Solution_3 {boolean[][] vis;int sum;int kk; // 代替k,定義全局變量,可以為dfs方法減少一個(gè)參數(shù)int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局變量的定義vis = new boolean[m][n];sum = 1; // (0,0)一定能被訪問(wèn)到kk = k; mm = m; nn = n;next = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 終止條件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 4; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否滿足條件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾經(jīng)走過(guò)這個(gè)點(diǎn)if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}}}// 解法4:由于從0,0開(kāi)始,因此只考慮向右or向下走即可。static class Solution_4 {boolean[][] vis;int sum;int kk; // 代替k,定義全局變量,可以為dfs方法減少一個(gè)參數(shù)int[][] next;int mm, nn;public int movingCount(int m, int n, int k) {// 全局變量的定義vis = new boolean[m][n];sum = 1; // (0,0)一定能被訪問(wèn)到kk = k; mm = m; nn = n;next = new int[][]{{1,0}, {0,1}};vis[0][0] = true;dfs(0, 0);return sum;}public void dfs(int x, int y) {// 終止條件if(x > mm || y > nn) return;// 回溯for(int i = 0; i < 2; i++) {int xx = x + next[i][0], yy = y + next[i][1];// 1、是否超界 or 是否滿足條件, continueif(xx < 0 || xx >= mm || yy < 0 || yy >= nn || (xx%10 + xx/10 + yy%10 + yy/10 > kk)) continue;// 2、是否曾經(jīng)走過(guò)這個(gè)點(diǎn)if(!vis[xx][yy]) {vis[xx][yy] = true;sum++;dfs(xx, yy);}}}}public static void main(String[] args) {Solution_2 solution_2 = new Solution_2();System.out.println(solution_2.movingCount(16, 8, 4));} }

總結(jié)

以上是生活随笔為你收集整理的【四重优化,速看】剑指 Offer 13. 机器人的运动范围的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。