1. 程式人生 > >劍指Offer演算法題及答案Java完整版(二)

劍指Offer演算法題及答案Java完整版(二)

16、請設計一個函式,用來判斷在一個矩陣中是否存在一條包含某字串所有字元的路徑,路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則之後不能再次進入這個格子。例如 a b c e s f c s a d e e 這樣的3 X 4 矩陣中包含一條字串”bcced”的路徑,但是矩陣中不包含”abcb”路徑,因為字串的第一個字元b佔據了矩陣中的第一行第二個格子之後,路徑不能再次進入該格子。

package cn.ctgu.offer;
/*
 * 題目:
 * 請設計一個函式,用來判斷在一個矩陣中是否存在一條包含某字串所有字元的路徑。
 * 路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。
 * 如果一條路徑經過了矩陣中的某一個格子,則之後不能再次進入這個格子。
 * 例如 a b c e s f c s a d e e 這樣的3 X 4 矩陣中包含一條字串"bcced"的路徑
 * 但是矩陣中不包含"abcb"路徑,因為字串的第一個字元b佔據了矩陣中的第一行第二個格子之後,路徑不能再次進入該格子。
 * 
 * 思路:
 * 1、採用回溯法
 * 2、將matrix字串模擬對映為一個字元矩陣(但並不實際建立一個矩陣)
 * 3、取一個boolean[matrix.length]標記某個字元是否已經被訪問過
 * 3、如果沒找到結果,需要將對應的boolean標記值置回false,返回上一層進行其他分路的查詢
 * 
 * */
public class HashStrPath {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        boolean[] visited=new boolean[matrix.length];
        for(int i=0;i<rows;i++) {
            for(int j=0;j<cols;j++) {
                if(searchFromHere(matrix,rows,cols,i,j,0,str,visited))
                    return true;
            }
        }
        return false;

    }

    private boolean searchFromHere(char[] matrix, int rows, int cols, int r, int c, int index, char[] str,
            boolean[] visited) {
        //matrix[r*cols+c]!=str[index]這是判斷位置(c,r)是否為字串所在位置
        if(r<0 || r>=rows || c<0 ||c>=cols || matrix[r*cols+c]!=str[index] || visited[r * cols + c])
            return false;
        if(index==str.length-1)
            return true;
        visited[r*cols+c]=true;
        if (searchFromHere(matrix,rows,cols,r - 1,c,index + 1,str,visited) ||
                    searchFromHere(matrix,rows,cols,r,c -1,index + 1,str,visited) ||
                    searchFromHere(matrix,rows,cols,r + 1,c,index + 1,str,visited) ||
                    searchFromHere(matrix,rows,cols,r,c + 1,index + 1,str,visited))
                return true;
        visited[r*cols+c]=false;
        return false;
    }
}

17、給定一個double型別的浮點數base和int型別的整數exponent。求base的exponent次方。

package cn.ctgu.offer;
/*
 * 給定一個double型別的浮點數base和int型別的整數exponent。
 * 求base的exponent次方。
 * 
 * 
 * */
public class IntegerPower {
    public double Power(double base, int exponent) {

        return Math.pow(base, exponent);
      }
    /*手寫
     * 
     * 1.全面考察指數的正負、底數是否為零等情況。
     * 2.寫出指數的二進位制表達,例如13表達為二進位制1101。
     * 3.舉例:10^1101 = 10^0001*10^0100*10^1000。
     * 4.通過&1和>>1來逐位讀取1101,為1時將該位代表的乘數累乘到最終結果。
     * 
     * */
    public double Power2(double base, int n) {
        double res = 1,curr = base;
        int exponent;
        if(n>0){
            exponent = n;
        }else if(n<0){
            if(base==0)
                throw new RuntimeException("分母不能為0"); 
            exponent = -n;
        }else{// n==0
            return 1;// 0的0次方
        }
        while(exponent!=0){
            if((exponent&1)==1)
                res*=curr;
            curr*=curr;// 翻倍
            exponent>>=1;// 右移一位
        }
        return n>=0?res:(1/res);       
    }
    public static void main(String[]args) {
        IntegerPower num=new IntegerPower();
        System.out.println(num.Power2(12.34d, -4));
    }
}

18、LL今天心情特別好,因為他去買了一副撲克牌,發現裡面居然有2個大王,2個小王(一副牌原本是54張^_^)…他隨機從中抽出了5張牌,想測測自己的手氣,看看能不能抽到順子,如果抽到的話,他決定去買體育彩票,嘿嘿!!“紅心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是順子…..LL不高興了,他想了想,決定大\小 王可以看成任何數字,並且A看作1,J為11,Q為12,K為13。上面的5張牌就可以變成“1,2,3,4,5”(大小王分別看作2和4),“So Lucky!”。現在,要求你使用這幅牌模擬上面的過程,然後告訴我們LL的運氣如何, 如果牌能組成順子就輸出true,否則就輸出false。

package cn.ctgu.offer;

import java.util.Arrays;

/*
 * 題目:
 * LL今天心情特別好,因為他去買了一副撲克牌,發現裡面居然有2個大王,2個小王(一副牌原本是54張^_^)...
 * 他隨機從中抽出了5張牌,想測測自己的手氣,看看能不能抽到順子,如果抽到的話,他決定去買體育彩票,嘿嘿!!
 * “紅心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是順子.....LL不高興了
 * 他想了想,決定大\小 王可以看成任何數字,並且A看作1,J為11,Q為12,K為13。
 * 上面的5張牌就可以變成“1,2,3,4,5”(大小王分別看作2和4),“So Lucky!”。
 * 現在,要求你使用這幅牌模擬上面的過程,然後告訴我們LL的運氣如何, 如果牌能組成順子就輸出true,否則就輸出false。
 * 
 * 
 * 思路:
 * 1、當牌不等於5張的時候返回false
 * 2、對排進行排序(方便統計王(0)的數量以及比較是否有相同的牌,前後比較即可)
 * 3、判斷第一張非0的牌和最後一張非0的牌的差是否超過4,如果超過4則不可能是順子
 * 
 * */
public class IsContinu {
    public boolean isContinuous(int [] numbers) {
        if(numbers.length!=5) {
            return false;
        }
        //排序
        Arrays.sort(numbers);
        //統計王的個數
        int res=0;
        for(int i=0;i<numbers.length;i++) {
            if(numbers[i]==0) {
                res=res+1;
                continue;
            }
            //當王的數量小於等於3張的時候才需要判斷,等於4張的時候一定是順子
            //判斷第一張非0的牌和最後一張非0的牌的差值吃否超過4
            //判斷前後兩張牌是否相等,相等則不可能是順子
            //此時的numbers[i]為第一個不為0的數,因為前面將為0的資料都遍歷完了(continue的作用是跳出本輪迴圈,繼續下一輪,所以0沒有遍歷完之前不會執行下面的語句)
            if(res!=4&&(numbers[numbers.length-1]-numbers[i]>4||numbers[i]==numbers[i+1])) {
                return false;
            }else {
                return true;
            }
        }
        return true;
    }
}

19、請實現一個函式用來判斷字串是否表示數值(包括整數和小數)。例如,字串”+100”,”5e2”,”-123”,”3.1416”和”-1E-16”都表示數值。但是”12e”,”1a3.14”,”1.2.3”,”+-5”和”12e+4.3”都不是。

package cn.ctgu.offer;
/*
 * 題目:
 * 請實現一個函式用來判斷字串是否表示數值(包括整數和小數)。
 * 例如,字串"+100","5e2","-123","3.1416"和"-1E-16"都表示數值。
 * 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
 * 
 * 
 * 思路:
 * 1、先掃描字元是否是以+、-開頭,如果是則判斷下一個字元是否為數字,只有數字才能通過,否則該字串不表示數值;
 *   如果不是+、-,則判斷它是否是數字
 * 2、如果是數字則進行下一個字元判斷,判斷它是否為數字,如果不是則進行"."判斷和"E、e"判斷,反正第二個字元只能為數字或者"E、e"(第一個字元如果為'+、-'則第二個字元只能為數字)
 *    如果第一個字元為數字,則第二個字元可以為('-、E、e、.')
 * 
 * 
 * */
public class IsNumber {
    private int index=0;
    public boolean isNumberic(char[] str) {
        if(str.length<1)
            return false;
        boolean flag=scanInteger(str);

        if(index<str.length && str[index]=='.') {
            index++;
            flag=scanUnsignedInteger(str)||flag;//字元如果不為數字則返回false
        }
        if(index<str.length && (str[index]=='E'||str[index]=='e')) {
            index++;
            flag=flag && scanInteger(str);
        }
        return flag && index==str.length;
    }
    //判斷字元是否是以+或-號開頭
    private boolean scanInteger(char[] str) {
        if(index<str.length &&(str[index]=='+'||str[index]=='-'))
            index++;
        //如果不是+、-就判斷是否為數字
        return scanUnsignedInteger(str);
    }
    private boolean scanUnsignedInteger(char[] str) {
        int start=index;
        while(index<str.length && str[index]>='0'&& str[index]<='9')
            index++;
        return start<index;//是否存在整數
    }
}

20、輸入一個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則輸出Yes,否則輸出No。假設輸入的陣列的任意兩個數字都互不相同。說明:二叉搜尋樹的根節點大於左子樹,右節點大於根節點

package cn.ctgu.offer;
/*
 * 輸入一個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則輸出Yes,否則輸出No。
 * 假設輸入的陣列的任意兩個數字都互不相同。
 * 說明:二叉搜尋樹的根節點大於左子樹,右節點大於根節點
 * 
 * 思路:
 * 1、採用遞迴
 * 2、去掉根節點,也就是陣列的最後一個元素,小於最後一個節點的為左子樹,大於根節點的為右子樹
 * 3、如果左子樹和右子樹都滿足左節點小於根節點、右節點大於根節點則為true,否則為true
 * 
 * 
 * */
public class JudgeBST {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence.length==0) {
            return false;
        }
        return IsBst(sequence,0,sequence.length-1);
    }
    public boolean IsBst(int[]sequence,int start,int end ) {
        if(end<=start) {//當只有一個元素時,則為真
            return true;
        }
        int i=start;
        for(;i<end;i++) {
            if(sequence[i]>sequence[end]) {//當找到某個節點大於根節點,則從該元素開始直到end-1(倒數第二個元素),都為左子樹
                break;
            }
        }
        for(int j=i;j<end;j++) {    //如果右子樹中存在小於根節點的元素,則返回false,即該陣列不是二叉搜尋樹的後序遍歷
            if(sequence[j]<sequence[end]) {
                return false;
            }
        }
        return IsBst(sequence,start,i-1) && IsBst(sequence,i,end-1);
    }

}

21、一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法

package cn.ctgu.offer;
/*
 * 一隻青蛙一次可以跳上1級臺階,也可以跳上2級。
 * 求該青蛙跳上一個n級的臺階總共有多少種跳法
 * 
 * 思路:當前臺階的跳法總數=當前臺階後退一階的臺階的跳法總數+當前臺階後退二階的臺階的跳法總數
 * 
 * 
 * 使用動態規劃來求解該問題,動態規劃適合求解最優解問題。
 * 1、先構造出最優子結構
 * 2、建立遞迴關係
 * 3、計算最優值
 * 4、求解最優解
 * 
 * */
public class JumpFloor {
    public int JumpFloors(int target) {
        if(target==1) {
            return 1;
        }
        if(target==2) {
            return 2;
        }
        int one=1;//當前臺階後退二階的臺階的跳法總數(初始值當前臺階是第3階)
        int two=2;//當前臺階後退一階的臺階的跳法總數(初始值當前臺階是第3階)
        int result=0;// 當前臺階的跳法總數
        for(int i=2;i<target;i++) {
            result=one+two;
            one=two;//後退一階在下一次迭代變為後退兩階
            two=result;//當前臺階在下一次迭代變為後退一階
        }
        return result;
    }
    public static void main(String[]args) {
        JumpFloor dy=new JumpFloor();
        System.out.println(dy.JumpFloors(3));
    }

}

22、一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

package cn.ctgu.offer;
/*
 *一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。
 *求該青蛙跳上一個n級的臺階總共有多少種跳法。
 *
 * 思路:設跳上第n階的跳法為f(n)
 * 即 f(n)=f(n-1)+f(n-2)+f(n-3)+...+f(1)+1
 * 
 * 1就是直接跳上第n階樓梯的跳法
 * 
 * */
public class JumpFloor2 {
    public int JumpFloor(int target) {
        int[]ways=new int[target+1];
        ways[0]=1;
        ways[1]=1;//跳上一級階梯有一種跳法
        if(target==0) {
            return 0;
        }
        else {
            for(int i=2;i<=target;i++) {
                ways[i]=0;//相當於那個1,也就是直接跳上第n階樓梯的跳法
            for(int j=0;j<i;j++) {
                ways[i]=ways[i]+ways[j];
            }
        }
        return ways[target];
    }
}
    public static void main(String[]args) {
        JumpFloor2 dy=new JumpFloor2();
        System.out.println(dy.JumpFloor(5));
    }

}

23、隨機指定一個數m,讓編號為0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中。從他的下一個小朋友開始,繼續0…m-1報數….這樣下去….直到剩下最後一個小朋友。可以不用表演,並且拿到牛客名貴的“名偵探柯南”典藏版(名額有限哦!!^_^)。請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)

package cn.ctgu.offer;

import java.util.LinkedList;

/*
 * 題目:
 * 隨機指定一個數m,讓編號為0的小朋友開始報數。
 * 每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中。
 * 從他的下一個小朋友開始,繼續0...m-1報數....這樣下去....直到剩下最後一個小朋友。
 * 可以不用表演,並且拿到牛客名貴的“名偵探柯南”典藏版(名額有限哦!!^_^)。
 * 請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)
 * 
 * 
 * 思路:
 * 1、將所有的數封裝成一個LinkedList
 * 2、每次刪除的都是第m-1個元素,它的索引可以通過公式:index=(index+m-1)%(環的長度)得到
 * 3、index是指開始那個元素的索引,比如,因為每次報數都是從0開始,m為2的話刪除的必定為1(m=2,2-1=1)
 * 4、將原始索引為1的刪除了的話,下一個開始的元素報0的數為原始索引為2的元素(由於是連結串列,則刪除了索引為1的元素
 *    後面的元素自然前移,即原來索引為2的元素自然為1,也就是被刪除的原索引本身)
 * 
 * */
public class LastRemain {
    public int LastRemaining_Solution(int n, int m) {
        LinkedList<Integer>list=new LinkedList<Integer>();
        //將所有的數封裝到LinkedList中
        for(int i=0;i<n;i++) {
            list.add(i);
        }
        //刪除元素
        int index=0;
        while(list.size()>1) {
            index=(index+m-1)%list.size();
            list.remove(index);
        }
        return list.size()==1?list.get(0):-1;
    }
}

24、例如,字元序列S=”abcXYZdef”,要求輸出迴圈左移3位後的結果,即“XYZdefabc”。

package cn.ctgu.offer;
/*
 * 題目:
 * 例如,字元序列S=”abcXYZdef”,要求輸出迴圈左移3位後的結果,即“XYZdefabc”。
 * 
 * 思路:
 * 1、將字串轉成字串陣列
 * 2、左移k位就把前k位取出來接在原陣列的後面
 * 
 * 
 * */
public class LeftRotateStr {
     public String LeftRotateString(String str,int n) {
         int len=str.length();
         if(len==0) {
             return "";
         }
         if(n>len) {
             n=n-len;
         }
         char[]strArray=str.toCharArray();
         char[]newArray=new char[len];
         for(int i=n;i<len;i++) {
             newArray[i-n]=strArray[i];
         }
         for(int j=0;j<n;j++) {
             newArray[len-n+j]=strArray[j];
         }
         return String.valueOf(newArray);
     }
     public static void main(String[]args) {
         LeftRotateStr solution=new LeftRotateStr();
         String s="abcXYZdef";
         String str=solution.LeftRotateString(s, 3);
         System.out.println(str);
     }
}

25、在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。

/*兩種思路
一種是:
把每一行看成有序遞增的陣列,
利用二分查詢,
通過遍歷每一行得到答案,
時間複雜度是nlogn
*/
public class Solution {
    public boolean Find(int [][] array,int target) {

        for(int i=0;i<array.length;i++){
            int low=0;
            int high=array[i].length-1;
            while(low<=high){
                int mid=(low+high)/2;
                if(target>array[i][mid])
                    low=mid+1;
                else if(target<array[i][mid])
                    high=mid-1;
                else
                    return true;
            }
        }
        return false;

    }
}
 /*
另外一種思路是:
利用二維陣列由上到下,由左到右遞增的規律,
那麼選取右上角或者左下角的元素a[row][col]與target進行比較,
當target小於元素a[row][col]時,那麼target必定在元素a所在行的左邊,
即col--;
當target大於元素a[row][col]時,那麼target必定在元素a所在列的下邊,
即row++;
*/
public class Solution {
    public boolean Find(int [][] array,int target) {
        int row=0;
        int col=array[0].length-1;
        while(row<=array.length-1&&col>=0){
            if(target==array[row][col])
                return true;
            else if(target>array[row][col])
                row++;
            else
                col--;
        }
        return false;

    }
}



26、給定一個數組和滑動視窗的大小,找出所有滑動窗口裡數值的最大值。例如,如果輸入陣列{2,3,4,2,6,2,5,1}及滑動視窗的大小3,那麼一共存在6個滑動視窗,他們的最大值分別為{4,4,6,6,6,5};針對陣列{2,3,4,2,6,2,5,1}的滑動視窗有以下6個:{[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1},{2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

package cn.ctgu.offer;

import java.util.ArrayList;

/*
 * 題目:
 * 給定一個數組和滑動視窗的大小,找出所有滑動窗口裡數值的最大值。
 * 例如,如果輸入陣列{2,3,4,2,6,2,5,1}及滑動視窗的大小3
 * 那麼一共存在6個滑動視窗,他們的最大值分別為{4,4,6,6,6,5}; 
 * 針對陣列{2,3,4,2,6,2,5,1}的滑動視窗有以下6個:
 *  {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1},
 *  {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
 * 
 * 思路:
 * 1、每隔一個視窗長度找出最大的值
 * 2、將最大的值新增進列表
 * */
public class MaxInWindow {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer>list=new ArrayList<Integer>();
        if(size>num.length||size==0)
            return list;
        for(int i=0;i<=num.length-size;i++) {
            int max=num[i];
            for(int j=i+1;j<i+size;j++) {
                if(num[j]>max) {
                    max=num[j];
                }
            }
            list.add(max);
        }
        return list;
    }
}

27、歸併排序演算法

package cn.ctgu.offer;

import java.util.Arrays;

/*
 * 歸併排序
 * 
 * */
public class MergeSort {
    public static void sort(int []arr) {
        //排序前,先建好一個長度等於原陣列長度的臨時陣列,避免遞迴中頻繁開闢空間
        int[] temp=new int[arr.length];
        sort(arr,0,arr.length-1,temp);
    }

    private static void sort(int[] arr, int left, int right, int[] temp) {
        if(left<right) {
            int mid=(left+right)/2;
            //左邊歸併排序,使得左子序列有序
            sort(arr,left,mid,temp);
            //右邊歸併排序,使得右子序列有序
            sort(arr,mid+1,right,temp);
            //將兩個有序子數組合並操作
            merge(arr,left,mid,right,temp);
        }

    }

    private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        //左序列指標
        int i=left;
        //右序列指標
        int j=mid+1;
        //臨時陣列指標
        int t=0;
        while(i<=mid && j<right) {
            if(arr[i]<=arr[j]) {
                temp[t]=arr[i];
                t++;
                i++;
            }else{
                temp[t]=arr[j];
                t++;
                j++;
            }
        }
        while(i<=mid) {//將左邊剩餘元素填充進temp中
            temp[t]=arr[i];
            t++;
            i++;
        }
        while(j<=right) {//將右序列剩餘元素填充進temp中
            temp[t]=arr[j];
            t++;
            j++;
        }
        t=0;
        //將temp中的元素全部拷貝到原陣列中
        while(left<=right) {
            arr[left]=temp[t];
            left++;
            t++;
        }

    }
     public static void main(String []args){
            int []arr = {9,8,7,6,5,4,3,2,1};
            sort(arr);
            System.out.println(Arrays.toString(arr));
        }
}

28、輸入一個正整數陣列,把數組裡所有數字拼接起來排成一個數,列印能拼接出的所有數字中最小的一個。例如輸入陣列{3,32,321},則打印出這三個數字能排成的最小數字為321323。

package cn.ctgu.offer;
/*
 * 題目:
 * 輸入一個正整數陣列,把數組裡所有數字拼接起來排成一個數,列印能拼接出的所有數字中最小的一個。
 * 例如輸入陣列{3,32,321},則打印出這三個數字能排成的最小數字為321323。
 * 
 * 思路:
 * 兩兩比較,自定義一個比較大小的函式
 * 比較兩個字串s1, s2大小的時候,先將它們拼接起來
 * 比較s1+s2,和s2+s1那個大,如果s1+s2大,那說明s2應該放前面
 * 所以按這個規則,s2就應該排在s1前面。
 * 
 * */
public class MinArrayNumber {
     public String PrintMinNumber(int [] numbers) {
            String str="";
            for(int i=0;i<numbers.length;i++) {
                for(int j=i+1;j<numbers.length;j++) {
                    int a=Integer.valueOf(numbers[i]+""+numbers[j]);
                    int b=Integer.valueOf(numbers[j]+""+numbers[i]);
                    if(a>b) {
                        int t=numbers[i];
                        numbers[i]=numbers[j];
                        numbers[j]=t;
                    }
                }
            }
            for(int i=0;i<numbers.length;i++) {
                str+=String.valueOf(numbers[i]);
            }
            return str;
     }
     public static void main(String[]args) {
         MinArrayNumber solution=new MinArrayNumber();
         int[] num= {3,32,321};
         String str=solution.PrintMinNumber(num);
         System.out.println(str);
     }
}

29、定義棧的資料結構,請在該型別中實現一個能夠得到棧最小元素的min函式。

package cn.ctgu.offer;
import java.util.Iterator;
import java.util.Stack;
/*
 * 定義棧的資料結構,請在該型別中實現一個能夠得到棧最小元素的min函式。
 * 
 * 
 * 
 * 
 * */
public class MinStack {
    Stack<Integer> stack=new Stack<Integer>();
    public void push(int node) {
        stack.push(node);
    }

    public void pop() {
        stack.pop();
    }

    public int top() {
        return stack.peek(); //棧頂元素(也就是最後一個元素)
    }

    public int min() {
        int min = stack.peek();
        int tmp=0;
        Iterator<Integer> iterator = stack.iterator();
        while (iterator.hasNext()){
            tmp = iterator.next();
            if (min>tmp){
                min = tmp;
            }
        }
        return min;
    }
}

30、地上有一個m行和n列的方格。一個機器人從座標0,0的格子開始移動,每一次只能向左,右,上,下四個方向移動一格,但是不能進入行座標和列座標的數位之和大於k的格子。例如,當k為18時,機器人能夠進入方格(35,37),因為3+5+3+7 = 18。但是,它不能進入方格(35,38),因為3+5+3+8 = 19。請問該機器人能夠達到多少個格子?

package cn.ctgu.offer;
/*
 * 題目:
 * 地上有一個m行和n列的方格。
 * 一個機器人從座標0,0的格子開始移動,每一次只能向左,右,上,下四個方向移動一格
 * 但是不能進入行座標和列座標的數位之和大於k的格子。
 * 例如,當k為18時,機器人能夠進入方格(35,37),因為3+5+3+7 = 18。
 * 但是,它不能進入方格(35,38),因為3+5+3+8 = 19。請問該機器人能夠達到多少個格子?
 * 
 * 思路:
 * 1、回溯法
 * 2、從(0,0)開始走,每成功走一步標記當前位置為true,然後從當前位置往四個方向探索
 *   返回1+4個方向的探索值之和
 * 3、探索時,判斷當前結點是否可達的標準為:
 *      1)當前結點在矩陣內
 *      2)當前結點未被訪問過
 *      3)當前結點滿足limit限制
 * 
 * */
public class MoveCount {
    public int movingCount(int threshold, int rows, int cols) {
        boolean[][]visited=new boolean[rows][cols];
        return countingSteps(threshold,rows,cols,0,0,visited);
    }

    private int countingSteps(int limit, int rows, int cols, int r, int c, boolean[][] visited) {

        if(r<0||r>=rows||c<0||c>=cols||visited[r][c]||bitSum(r)+bitSum(c)>limit)
            return 0;
        visited[r][c]=true;

        return countingSteps(limit,rows,cols,r - 1,c,visited)
                            + countingSteps(limit,rows,cols,r,c - 1,visited)
                            + countingSteps(limit,rows,cols,r + 1,c,visited)
                            + countingSteps(limit,rows,cols,r,c + 1,visited)
                            + 1;
    }

    private int bitSum(int t) {
        int count=0;
        while(t!=0) {
            count=count+t%10;
            t=t/10;
        }
        return count;
    }
}