<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于回溯算法的解題模板

          共 5029字,需瀏覽 11分鐘

           ·

          2022-01-23 03:40

          回溯算法作為一種經(jīng)典的有效的暴力搜索策略。其基本思想是搜索過程中沿著一條路徑一直往前走,當(dāng)探索到某一步時(shí)發(fā)現(xiàn)無法滿足要求時(shí),則退回到上一步選擇另外一條路徑繼續(xù)往前搜索。對(duì)于許多大規(guī)模復(fù)雜問題而言,很多時(shí)候都可以通過回溯算法嘗試解決

          abstract.png

          算法模板

          結(jié)合LeetCode刷題經(jīng)驗(yàn),現(xiàn)對(duì)回溯算法的解題思路進(jìn)行總結(jié),并形成下面的偽代碼模板。我們首先需要兩個(gè)全局變量:result、state。前者用于保存最終搜索結(jié)果;后者用于記錄搜索過程中的狀態(tài)信息。故在程序入口getResult方法中首先需要通過init方法完成全局變量的初始化,最后直接返回全局變量result作為題解即可。而這期間通過search方法進(jìn)行回溯搜索即可

          search方法的最重要思路是根據(jù)當(dāng)前狀態(tài)等信息獲取下一步搜索的可選擇空間,即通過調(diào)用getAvailableList方法實(shí)現(xiàn),然后遍歷該可選擇空間。具體地對(duì)于每個(gè)選擇,先判斷是否符合條件。如果符合,則說明可以選擇它繼續(xù)往前搜索。那么我們第1步先做出選擇,包括對(duì)狀態(tài)變量state的更新;第2步通過遞歸調(diào)用search方法實(shí)現(xiàn)所謂的一直往前搜索;第3步當(dāng)遞歸調(diào)用結(jié)束返回時(shí)則說明已經(jīng)當(dāng)前搜索路徑已經(jīng)退回到上一步了,這個(gè)時(shí)候我們就需要撤銷第1步做出的選擇對(duì)狀態(tài)變量的影響了??偠灾?,回溯的關(guān)鍵就在于在遞歸搜索之前需要做出選擇,而在遞歸搜索之后需要撤銷選擇

          前面提到search方法會(huì)一直遞歸調(diào)用下去。那遞歸終止條件是什么呢?其實(shí)也很簡(jiǎn)單,第一種是發(fā)現(xiàn)不滿足合法條件時(shí)直接return,即所謂的剪枝優(yōu)化;第二種則是搜索成功,此時(shí)需要根據(jù)狀態(tài)等信息將當(dāng)前的搜索結(jié)果添加最終結(jié)果當(dāng)中去

          /**
          ?*?回溯算法模板
          ?*/

          public?static?class?Solution?{
          ????//?全局變量:?最終結(jié)果
          ????private?result;

          ????//?全局變量:?當(dāng)前搜索過程的狀態(tài)信息
          ????private?state;

          ????/**
          ?????*?入口
          ?????*/

          ????public?getResult(...)?{
          ????????//?Step?1:?初始化全局變量
          ????????init(...);
          ????????//?Step?2:?回溯法搜索
          ????????search(...);
          ????????//?Step?3:?直接返回搜索結(jié)果
          ????????return?result;
          ????}

          ????/**
          ?????*?初始化全局變量
          ?????*/

          ????private?void?init(...)?{
          ????????result?=?...
          ????????state?=?...
          ????}

          ????/**
          ?????*?基于回溯算法的搜索
          ?????*/

          ????private?void?search(...)?{
          ????????//?剪枝
          ????????if(?不滿足合法條件?)?{
          ????????????return;
          ????????}?
          ????????
          ????????//?搜索成功
          ????????if(?滿足搜索結(jié)束條件?)?{
          ????????????//?根據(jù)當(dāng)前狀態(tài)信息,?更新result結(jié)果
          ????????????...
          ????????????return;
          ????????}

          ????????//?根據(jù)當(dāng)前狀態(tài)獲取選擇列表
          ????????availableList?=?getAvailableList(...);
          ????????//?遍歷選擇列表
          ????????for(int[]?tempIndex?:?availableList)?{
          ????????????if(?判斷當(dāng)前選擇?是否滿足?合法條件?)?{
          ????????????????//?1.?做選擇:?更新狀態(tài)信息
          ????????????????...
          ????????????????//?2.?遞歸搜索下一步
          ????????????????search(...)
          ????????????????//?3.?撤銷選擇:?撤銷對(duì)狀態(tài)信息的修改操作
          ????????????????...

          ????????????}
          ????????}
          ????}

          ????/**
          ?????*?根據(jù)當(dāng)前狀態(tài)獲取選擇列表
          ?????*/

          ????private?getAvailableList(...)?{
          ????????...
          ????}
          }

          實(shí)踐

          LeetCode: 17. 電話號(hào)碼的字母組合

          這里以 LeetCode 第17題 <電話號(hào)碼的字母組合> 為具體示例來進(jìn)行闡述

          給定一個(gè)僅包含數(shù)字 2-9 的字符串,返回所有它能表示的字母組合。答案可以按 任意順序 返回。數(shù)字到字母的映射如下圖(與電話按鍵相同),注意1不對(duì)應(yīng)任何字母

          figure 1.png

          示例 1:?

          輸入:digits = "23"?

          輸出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

          示例 2:?

          輸入:digits = ""?

          輸出:[]

          示例 3:?

          輸入:digits = "2"?

          輸出:["a","b","c"]

          按照模板則解法如下所示。由于本題在搜索過程中,任意一個(gè)搜索都是合法的,故不需要判斷每次選擇的合法性,直接按照 “做出選擇-遞歸搜索下一個(gè)-撤銷選擇” 的思路進(jìn)行處理即可

          /**
          ?*?回溯法
          ?*/

          public?static?class?Solution?{
          ????/**
          ?????*?數(shù)字與字符的映射,?key:?數(shù)字,?value:?字母
          ?????*/

          ????private?static??Map?num2StringMap;

          ????static?{
          ????????num2StringMap?=?new?HashMap<>();
          ????????num2StringMap.put('2',?"abc");
          ????????num2StringMap.put('3',?"def");
          ????????num2StringMap.put('4',?"ghi");
          ????????num2StringMap.put('5',?"jkl");
          ????????num2StringMap.put('6',?"mno");
          ????????num2StringMap.put('7',?"pqrs");
          ????????num2StringMap.put('8',?"tuv");
          ????????num2StringMap.put('9',?"wxyz");
          ????}

          ????/**
          ?????*?最終結(jié)果:?字母組合列表
          ?????*/

          ????private?List?result;

          ????/**
          ?????*?狀態(tài)變量:當(dāng)前搜索結(jié)果
          ?????*/

          ????private?StringBuilder?sb;

          ????public?List?letterCombinations(String?digits)?{
          ????????//?判空
          ????????if(?digits==null?||?digits.length()==0?)?{
          ????????????return?Collections.emptyList();
          ????????}

          ????????//?初始化全局變量
          ????????init();
          ????????//?從第0個(gè)數(shù)開始搜索
          ????????search(digits,?0);
          ????????//?直接返回最終搜索結(jié)果
          ????????return?result;
          ????}

          ????/**
          ?????*?初始化全局變量
          ?????*/

          ????private?void?init()?{
          ????????result?=?new?LinkedList<>();
          ????????sb?=?new?StringBuilder();
          ????}

          ????/**
          ?????*?回溯法遞歸搜索
          ?????*?@param?digits?待搜索數(shù)字
          ?????*?@param?index?搜索第index個(gè)數(shù)字
          ?????*/

          ????private?void?search(String?digits,?int?index)?{
          ????????//?數(shù)字全部搜索結(jié)束
          ????????if(?index?==?digits.length()?)?{
          ????????????//?將當(dāng)前搜索結(jié)果加入最終結(jié)果集
          ????????????result.add(?sb.toString()?);
          ????????????return;
          ????????}

          ????????//?獲取第index個(gè)數(shù)字的可選擇字符
          ????????char?num?=?digits.charAt(index);
          ????????String?choice?=?getChooseList(num);
          ????????//?遍歷可選擇字符
          ????????for(char?ch?:?choice.toCharArray()?)?{
          ????????????//?將當(dāng)前字符加入搜索結(jié)果
          ????????????sb.append(?ch?);
          ????????????//?遞歸搜索下一個(gè)數(shù)字
          ????????????search(digits,?index+1);
          ????????????//?將當(dāng)前字符從搜索結(jié)果中移除,?即撤銷所做出的選擇,?以進(jìn)行for循環(huán)的下一次遍歷
          ????????????sb.deleteCharAt(?sb.length()-1?);
          ????????}
          ????}

          ????/**
          ?????*?當(dāng)前數(shù)字的可選擇字符
          ?????*?@param?ch
          ?????*?@return
          ?????*/

          ????private?String?getChooseList(char?ch)?{
          ????????return?num2StringMap.get(ch);
          ????}
          }

          LeetCode: 51. N皇后

          這里以 LeetCode 第51題 為具體示例來進(jìn)行闡述

          n 皇后問題 研究的是如何將 n 個(gè)皇后放置在 n×n 的棋盤上,并且使皇后彼此之間不能相互攻擊。給你一個(gè)整數(shù) n ,返回所有不同的 n 皇后問題 的解決方案。每一種解法包含一個(gè)不同的 n 皇后問題 的棋子放置方案,該方案中 'Q' 和 '.' 分別代表了皇后和空位

          示例 1:?

          輸入:n = 4?

          輸出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]?

          解釋:如下圖所示,4皇后問題存在兩個(gè)不同的解法

          figure 2.png

          示例 2:?

          輸入:n = 1?

          輸出:[["Q"]]

          按照模板則解法如下所示。本題中對(duì)于皇后的放置位置有一定要求,棋盤中的行、列、斜線不同同時(shí)放置兩個(gè)皇后,故在遍歷時(shí)通過isValid方法保證當(dāng)前選擇的合法

          public?static?class?Solution?{
          ????/**
          ?????*?最終結(jié)果:所有N皇后問題的解決方案
          ?????*/

          ????private?List>?result;

          ????/**
          ?????*?狀態(tài)變量:n*n的棋盤布局, true:?表示相應(yīng)網(wǎng)格放置了皇后, false:?表示相應(yīng)網(wǎng)格未放置皇后
          ?????*/

          ????private?Boolean[][]?board;

          ????public?List>?solveNQueens(int?n)?{
          ????????init(n);
          ????????//?從第0行開始放置皇后
          ????????search(n,?0);
          ????????return?result;
          ????}

          ????/**
          ?????*?全局變量初始化
          ?????*?@param?n
          ?????*/

          ????private?void?init(int?n)?{
          ????????result?=?new?LinkedList<>();
          ????????board?=?new?Boolean[n][n];
          ????????for(int?i=0;?i????????????Arrays.fill(?board[i],?false?);
          ????????}
          ????}

          ????/**
          ?????*?遞歸法搜索
          ?????*?@param?n
          ?????*?@param?rowIndex?放置第rowIndex行的皇后
          ?????*/

          ????private?void?search(int?n,?int?rowIndex)?{
          ????????//?N個(gè)皇后全部放置完畢
          ????????if(rowIndex?==?n)?{
          ????????????//?將狀態(tài)變量轉(zhuǎn)換為棋盤布局,?并添加到最終結(jié)果當(dāng)中
          ????????????convert();
          ????????????return;
          ????????}

          ????????for(int?colIndex=0;?colIndex????????????if(?isValid(rowIndex,?colIndex)?)?{
          ????????????????board[rowIndex][colIndex]?=?true;
          ????????????????search(n,?rowIndex+1);
          ????????????????board[rowIndex][colIndex]?=?false;
          ????????????}
          ????????}

          ????}

          ????/**
          ?????*?判斷選擇的合法性
          ?????*?@param?rowIndex
          ?????*?@param?colIndex
          ?????*?@return
          ?????*/

          ????private?boolean?isValid(int?rowIndex,?int?colIndex)?{
          ????????//?所在列不能有皇后
          ????????for(int?i=0;?i????????????if(?board[i][colIndex])?{
          ????????????????return?false;
          ????????????}
          ????????}

          ????????//?所在主斜線的左上方部分不能有皇后
          ????????for(int?i=1;;i++)?{
          ????????????//?主斜線左上角的網(wǎng)格
          ????????????int?x1?=?rowIndex?-?i;
          ????????????int?y1?=?colIndex?-?i;
          ????????????//?網(wǎng)格均不在棋盤范圍內(nèi)
          ????????????if(?x1<0?||?y1<0?)?{
          ????????????????break;
          ????????????}
          ????????????//?存在包含皇后的網(wǎng)格
          ????????????if(?board[x1][y1]?)?{
          ????????????????return?false;
          ????????????}
          ????????}

          ????????//?所在次斜線的右上方部分不能有皇后
          ????????for(int?i=1;;?i++)?{
          ????????????int?x1?=?rowIndex?-?i;
          ????????????int?y1?=?colIndex?+?i;
          ????????????if(?x1<0?||?y1>board.length-1?)?{
          ????????????????break;
          ????????????}
          ????????????if(?board[x1][y1]?)?{
          ????????????????return?false;
          ????????????}
          ????????}

          ????????return?true;
          ????}

          ????/**
          ?????*?將狀態(tài)變量轉(zhuǎn)換為棋盤布局,?并添加到最終結(jié)果當(dāng)中
          ?????*/

          ????private?void?convert()?{
          ????????List?tempList?=?new?LinkedList<>();
          ????????for(int?i=0;?i????????????String?rowStr?=?Arrays.stream(?board[i]?)
          ????????????????.map(?e?->?{
          ????????????????????//?true:?表示相應(yīng)網(wǎng)格放置了皇后
          ????????????????????if(?e?)?{
          ????????????????????????return?"Q";
          ????????????????????}
          ????????????????????//?false:?表示相應(yīng)網(wǎng)格未放置皇后
          ????????????????????return?".";
          ????????????????}?)
          ????????????????.collect(Collectors.joining());
          ????????????tempList.add(?rowStr?);
          ????????}
          ????????result.add(?tempList?);
          ????}

          }

          劍指Offer(第2版): 12. 矩陣中的路徑

          這里以 LeetCode 的劍指Offer(第2版)題單中的第12題 <矩陣中的路徑> 為具體示例來進(jìn)行闡述

          給定一個(gè) m x n 二維字符網(wǎng)格 board 和一個(gè)字符串單詞 word 。如果 word 存在于網(wǎng)格中,返回 true ;否則,返回 false 。單詞必須按照字母順序,通過相鄰的單元格內(nèi)的字母構(gòu)成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個(gè)單元格內(nèi)的字母不允許被重復(fù)使用

          例如,在下面的 3×4 的矩陣中包含單詞 "ABCCED"(單詞中的字母已標(biāo)出)。

          figure 3.png

          示例 1:?

          輸入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"?

          輸出:true

          示例 2:?

          輸入:board = [["a","b"],["c","d"]], word = "abcd"?

          輸出:false

          按照模板則解法如下所示。一方面本題每次的搜索路徑為上、下、左、右這四個(gè)方向上未使用過的網(wǎng)絡(luò);另一方面本題只需判斷能夠搜索成功即可。所以當(dāng)?shù)谝淮嗡阉鞒晒?,即可以不再進(jìn)行搜索。故解法中加入了基于exist結(jié)果判斷的剪枝優(yōu)化

          /**
          ?*?回溯法
          ?*/

          public?static?class?Solution?{
          ????/**
          ?????*?行數(shù)
          ?????*/

          ????private?int?row;

          ????/**
          ?????*?列數(shù)
          ?????*/

          ????private?int?col;

          ????/**
          ?????*?最終結(jié)果標(biāo)記,?true:?找到;?false:?未找到
          ?????*/

          ????private?boolean?exist;

          ????/**
          ?????*?網(wǎng)格被訪問狀態(tài)標(biāo)記,?true:?該元素被訪問;?false:?該元素未被訪問
          ?????*/

          ????private?boolean[][]?usedArray;

          ????public?boolean?exist(char[][]?board,?String?word)?{
          ????????if(?board==null?||?board[0]==null?||?word==null?||?word==""?//?判空
          ????????????||?board.length*board[0].length?//?剪枝:?網(wǎng)格元素?cái)?shù)小于字符串?dāng)?shù)量,?肯定搜索不到
          ????????????return?false;
          ????????}

          ????????//?初始化全局變量
          ????????init(board,?word);
          ????????//?從字符串的第一個(gè)字符開始搜索
          ????????search(board,?word,?0,?0,?0);
          ????????return?exist;
          ????}

          ????/**
          ?????*?初始化全局變量
          ?????*?@param?board
          ?????*?@param?word
          ?????*/

          ????public?void?init(char[][]?board,?String?word)?{
          ????????exist?=?false;
          ????????row?=?board.length;
          ????????col?=?board[0].length;
          ????????usedArray?=?new?boolean[row][col];
          ????}

          ????/**
          ?????*?回溯法搜索
          ?????*?@param?board?網(wǎng)格
          ?????*?@param?word??字符串
          ?????*?@param?index?搜字符串的第index個(gè)字符
          ?????*?@param?i?網(wǎng)格元素的橫坐標(biāo)
          ?????*?@param?j?網(wǎng)格元素的縱坐標(biāo)
          ?????*/

          ????public?void?search(char[][]?board,?String?word,?int?index,?int?i,?int?j)?{
          ????????//?剪枝:?只要有一次搜索成功了即可結(jié)束搜索任務(wù)
          ????????if(?exist?)?{
          ????????????//?剪枝
          ????????????return;
          ????????}?else?if(?index?==?word.length()?)?{
          ????????????//?搜索成功,?更新結(jié)果,?并結(jié)束
          ????????????exist?=?true;
          ????????????return;
          ????????}

          ????????//?獲取選擇空間
          ????????Set<int[]>?indexSet?=?getAvailableIndexSet(index,?i,?j);
          ????????//?遍歷選擇空間
          ????????for(int[]?tempIndex?:?indexSet)?{

          ????????????//?剪枝:?只要有一次搜索成功了即可結(jié)束搜索任務(wù)
          ????????????if(exist)?{
          ????????????????break;
          ????????????}

          ????????????int?rowIndex?=?tempIndex[0];
          ????????????int?colIndex?=?tempIndex[1];
          ????????????//?字符串的第index個(gè)元素搜索成功
          ????????????if(?board[rowIndex][colIndex]?==?word.charAt(index)?)?{
          ????????????????//?將網(wǎng)格中相應(yīng)的元素標(biāo)記為?被訪問狀態(tài)
          ????????????????usedArray[rowIndex][colIndex]?=?true;
          ????????????????//?遞歸搜索字符串中的下一個(gè)元素
          ????????????????search(?board,?word,?index+1,?rowIndex,?colIndex);
          ????????????????//?將網(wǎng)格中相應(yīng)的元素標(biāo)記為?未被訪問狀態(tài),?即撤銷所做出的選擇,?以進(jìn)行for循環(huán)的下一次遍歷
          ????????????????usedArray[rowIndex][colIndex]?=?false;
          ????????????}
          ????????}
          ????}

          ????/**
          ?????*?獲取當(dāng)前網(wǎng)格元素的可選擇列表
          ?????*?@param?index
          ?????*?@param?i
          ?????*?@param?j
          ?????*?@return
          ?????*/

          ????public?Set<int[]>?getAvailableIndexSet(int?index,?int?i,?int?j)?{
          ????????//?自定義比較器:?當(dāng)兩個(gè)數(shù)組類型的元素,?如果數(shù)組中的內(nèi)容均相同則視為同一元素
          ????????Set<int[]>?indexSet?=?new?TreeSet<>(?(a1,?a2)?->?{
          ????????????if(?a1[0]?==?a2[0]?&&?a1[1]?==?a2[1]?)?{
          ????????????????return?0;
          ????????????}
          ????????????return?1;
          ????????});

          ????????//?搜索字符串第一個(gè)字符時(shí),?則可選擇的空間是整個(gè)網(wǎng)格
          ????????if(?index?==?0?)?{
          ????????????for(int?rowIndex=0;?rowIndex????????????????for?(int?colIndex=0;?colIndex????????????????????int[]?tempIndex?=?new?int[]{rowIndex,?colIndex};
          ????????????????????indexSet.add(?tempIndex?);
          ????????????????}
          ????????????}
          ????????????return?indexSet;
          ????????}

          ????????//?搜索字符串不是第一個(gè)字符時(shí),?則可選擇的空間是當(dāng)前網(wǎng)絡(luò)元素(i,j)的上、下、左、右這四個(gè)元素
          ????????int?iMax?=?i+1?<=?row-1???i+1?:?row-1;
          ????????int?iMin?=?i-1?>=?0???i-1?:?0;
          ????????int?jMax?=?j+1?<=?col-1???j+1?:?col-1;
          ????????int?jMin?=?j-1?>=?0???j-1?:?0;
          ????????indexSet.add(?new?int[]{iMin,?j}?);
          ????????indexSet.add(?new?int[]{iMax,?j}?);
          ????????indexSet.add(?new?int[]{i,?jMin}?);
          ????????indexSet.add(?new?int[]{i,?jMax}?);

          ????????//?選擇空間中的元素需要移除掉已經(jīng)被訪問過的
          ????????indexSet.removeIf(?tempIndex?->?{
          ????????????int?rowIndex?=?tempIndex[0];
          ????????????int?colIndex?=?tempIndex[1];
          ????????????return?usedArray[rowIndex][colIndex];
          ????????}?);

          ????????return?indexSet;
          ????}

          }

          劍指Offer(第2版): 13. 機(jī)器人的運(yùn)動(dòng)范圍

          這里以 LeetCode 的劍指Offer(第2版)題單中的第13題 <機(jī)器人的運(yùn)動(dòng)范圍> 為具體示例來進(jìn)行闡述

          地上有一個(gè)m行n列的方格,從坐標(biāo) [0,0] 到坐標(biāo) [m-1,n-1] 。一個(gè)機(jī)器人從坐標(biāo) [0, 0] 的格子開始移動(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)問該機(jī)器人能夠到達(dá)多少個(gè)格子?

          示例 1:?

          輸入:m = 2, n = 3, k = 1?

          輸出:3

          示例 2:?

          輸入:m = 3, n = 1, k = 0?

          輸出:1

          按照模板則解法如下所示。一方面本題每次的搜索路徑為下、右這兩個(gè)方向上未使用過的網(wǎng)絡(luò);另一方面本題要求的是統(tǒng)計(jì)機(jī)器人可以進(jìn)入的方格總數(shù)。故每進(jìn)入一個(gè)有效方格時(shí),需要更新統(tǒng)計(jì)值,并將該方格標(biāo)記為已訪問過。但需要注意的是本題在回溯之后,即遞歸返回后不需要撤銷所做出的選擇。即不能再將之前已經(jīng)訪問的方格從已訪問的狀態(tài)撤銷為未訪問的狀態(tài)。否則即會(huì)導(dǎo)致重復(fù)統(tǒng)計(jì)。換言之,在實(shí)際解題過程中不能生搬硬套解題模板。要善于理論聯(lián)系實(shí)際、靈活應(yīng)變。解題模板的作用在于總結(jié)經(jīng)驗(yàn)、沉淀認(rèn)知、減少解題的思維負(fù)擔(dān),它并不能完全取代、代替整個(gè)思考過程

          class?Solution?{
          ????/**
          ?????*?結(jié)果變量:?統(tǒng)計(jì)數(shù)
          ?????*/

          ????private?int?result;

          ????/**
          ?????*?狀態(tài)變量:?方格訪問標(biāo)記
          ?????*/
          ????
          ????private?boolean[][]?usedFlag;

          ????/**
          ?????*?方向向量:?向右、向下
          ?????*/

          ????private?int[]?dx?=?new?int[]{0,1};
          ????private?int[]?dy?=?new?int[]{1,0};

          ????public?int?movingCount(int?m,?int?n,?int?k)?{
          ????????if(?k<0?)?{
          ????????????return?0;
          ????????}

          ????????init(m,?n);
          ????????search(k,?0,?0);
          ????????return?result;
          ????}

          ????private?void?init(int?m,?int?n)?{
          ????????usedFlag?=?new?boolean[m][n];
          ????????//?起點(diǎn)(0,0)是合法的
          ????????usedFlag[0][0]?=?true;
          ????????result?=?1;
          ????}

          ????private?void?search(int?k,?int?rowIndex,?int?colIndex)?{
          ????????//?遍歷可選路徑
          ????????for(int?i=0;?i<2;?i++)?{
          ????????????//?計(jì)算可選路徑的坐標(biāo)
          ????????????int?nextRowIndex?=?rowIndex?+?dx[i];
          ????????????int?nextColIndex?=?colIndex?+?dy[i];

          ????????????//?滿足搜索條件
          ????????????if(?nextRowIndex>=0?&&?nextRowIndex<=usedFlag.length-1
          ????????????????&&?nextColIndex>=0?&&?nextColIndex<=usedFlag[0].length-1
          ????????????????&&?calcSum(nextRowIndex,?nextColIndex)<=k?&&?!usedFlag[nextRowIndex][nextColIndex]?)?{
          ????????????????//?更新計(jì)數(shù)值到結(jié)果變量
          ????????????????result++;
          ????????????????//?更新狀態(tài)變量,?將其設(shè)置為已訪問
          ????????????????usedFlag[nextRowIndex][nextColIndex]?=?true;
          ????????????????//?向下或向右繼續(xù)搜索
          ????????????????search(k,?nextRowIndex,?nextColIndex);
          ????????????}
          ????????}
          ????}

          ????/**
          ?????*?計(jì)算兩個(gè)數(shù)的數(shù)位之和
          ?????*?@param?num1
          ?????*?@param?num2
          ?????*?@return
          ?????*/

          ????private?int?calcSum(int?num1,?int?num2)?{
          ????????int?sum?=?0;
          ????????while(?num1!=0?)?{
          ????????????sum?+=?num1?%?10;???//?取個(gè)位進(jìn)行求和
          ????????????num1?=?num1?/?10;???//?移除個(gè)位
          ????????}
          ????????while(?num2!=0?)?{
          ????????????sum?+=?num2?%?10;
          ????????????num2?=?num2?/?10;
          ????????}
          ????????return?sum;
          ????}
          }
          瀏覽 64
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品视频一区二区 | 婷婷色五月在线 | 九九视频国产 | 成人毛片18男人毛片免小说 | 日韩中文在线观看 |