【劍指offer】1~10題

第一題:

在一個(gè)二維數(shù)組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個(gè)函數(shù),輸入這樣的一個(gè)二維數(shù)組和一個(gè)整數(shù),判斷數(shù)組中是否含有該整數(shù)。

????這是非常簡單的一道題,最常規(guī)的一種方式就是兩個(gè)方向上掃描,但是要保證其中一個(gè)掃描方向數(shù)字是遞增的,而另外一個(gè)方向上數(shù)字是遞減的。
????下面給出我的解法,從矩陣中的右上角開始,從右往左掃,當(dāng)橫向當(dāng)前數(shù)的下一個(gè)數(shù)小于目標(biāo)數(shù)的時(shí)候往下少,找到返回true,越界返回false。

public class Solution {
    public boolean Find(int target, int [][] array) {
        for(int i = array[0].length-1; i >= 0; i--) {
            if(array[0][i] <= target) {
                for(int j = 0; j < array.length; j++) {
                    if(array[j][i] == target) return true;
                }
            }
        }
        return false;
    }
}

第二題

請實(shí)現(xiàn)一個(gè)函數(shù),將一個(gè)字符串中的空格替換成“%20”。例如,當(dāng)字符串為We Are Happy.則經(jīng)過替換之后的字符串為We%20Are%20Happy。

????這題不解釋了,太簡單,很多編程語言直接用字符串處理函數(shù)就能做了,用正則也能做,當(dāng)然,題目本身可能并不希望你這么干。

public class Solution {
    public String replaceSpace(StringBuffer str) {
        char[] arr = str.toString().toCharArray();
        int len = arr.length;
        int blankCount = 0;
        for(int i = 0; i < len; i++) {
            if(arr[i] == ' ')
                blankCount++;
        }
         
        int[] res = new int[len+blankCount];
        int j = 0;
        for(int i = 0; i < len; i++) {
            if(arr[i] == ' ') {
                res[j++] = '%';
                res[j++] = '2';
                res[j++] = '0';
            } else {
                arr[j++] = arr[i];
            }
        }
         
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < res.length; i++) {
            sb.append(res[i]);
        }
        return sb.toString();
    }
}

第三題

輸入一個(gè)鏈表,從尾到頭打印鏈表每個(gè)節(jié)點(diǎn)的值。

????最簡單的思路就是用棧倒序輸出。

public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        Stack<Integer> stack = new Stack<>();
        while(listNode != null) {
            stack.push(listNode.val);
            listNode = listNode.next;
        }
        while(!stack.isEmpty()) {
            list.add(stack.pop());
        }
        return list;
    }
}

第四題

輸入某二叉樹的前序遍歷和中序遍歷的結(jié)果,請重建出該二叉樹。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹并返回。

????總算來了個(gè)比較有意思的題目。給你前序和中序,讓你重構(gòu)二叉樹返回。我們直接按題目中給的例子來講。
????前序遍歷是{1,2,4,7,3,5,6,8},也就是說 {1}這個(gè)數(shù)字就是根。而中序遍歷是{4,7,2,1,5,3,8,6},從而可以劃出兩個(gè)子集{4,7,2,1} {5,3,8,6}分別為組成以{1}為根的左右子樹。
????依照這個(gè)邏輯下去,就可以得出整棵樹的結(jié)構(gòu)了。這顯然就是一些重復(fù)步驟,用遞歸去做是最好的方式。再進(jìn)一步思考,我們只需要知道前序和中序遍歷的邊界下標(biāo),就能在遞歸過程中計(jì)算出我們要得到的數(shù)據(jù)。接下來,讓我們直接看代碼。

public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        return rebuilder(pre, in, 0, pre.length-1, 0, in.length-1);
    }
    
    public TreeNode rebuilder(int[] pre, int[] in, int prel, int prer, int inl, int inr) {
        if(prel > prer) return null;
        TreeNode node = new TreeNode(pre[prel]);
        for(int i = inl; i <= inr; i++) {
            if(in[i] == pre[prel]) {
                node.left = rebuilder(pre, in, prel+1, prel+i-inl, inl, i-1);
                node.right = rebuilder(pre, in, prel+i-inl+1, prer, i+1, inr);
                break;
            }
        }
        return node;
    }
}

第五題

用兩個(gè)棧來實(shí)現(xiàn)一個(gè)隊(duì)列,完成隊(duì)列的Push和Pop操作。 隊(duì)列中的元素為int類型。

????也是非常簡單的一題。要用兩個(gè)棧模擬隊(duì)列,我們只需要保持兩個(gè)原則。第一,當(dāng)你要push一個(gè)元素到其中一個(gè)棧時(shí)候,另外一個(gè)棧必須為空。第二,當(dāng)你要pop一個(gè)元素的時(shí)候,必須把棧中的所有元素傾倒到另外一個(gè)空棧,然后再pop數(shù)據(jù)出去。

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        while(!stack2.isEmpty()) {
            stack1.push(stack2.pop());
        }
        stack1.push(node);
    }
    
    public int pop() {
        while(!stack1.isEmpty()) {
            stack2.push(stack1.pop());
        }
        return stack2.pop();
    }
}

第六題

把一個(gè)數(shù)組最開始的若干個(gè)元素搬到數(shù)組的末尾,我們稱之為數(shù)組的旋轉(zhuǎn)。 輸入一個(gè)非遞減排序的數(shù)組的一個(gè)旋轉(zhuǎn),輸出旋轉(zhuǎn)數(shù)組的最小元素。 例如數(shù)組{3,4,5,1,2}為{1,2,3,4,5}的一個(gè)旋轉(zhuǎn),該數(shù)組的最小值為1。 NOTE:給出的所有元素都大于0,若數(shù)組大小為0,請返回0。

????咋看之下,這題似乎掃描一遍數(shù)組就行了。沒錯(cuò),確實(shí)如此,但是題目本身是希望你用二分去做的,不然給你非遞減這個(gè)特性就沒有意義了。題目說,非遞減數(shù)列做旋轉(zhuǎn),旋轉(zhuǎn)之后其實(shí)主要有兩種情況,一種就是旋轉(zhuǎn)后和旋轉(zhuǎn)前一樣,一種是旋轉(zhuǎn)后和選擇前發(fā)生了變化(這里暫時(shí)忽略數(shù)列中過的數(shù)全部相等的情況),第一種情況,數(shù)列的最后一個(gè)數(shù)一定是大于第一個(gè)數(shù)的。第二種情況,最小的數(shù)一定在數(shù)列中。而這個(gè)數(shù)列也會(huì)分成兩個(gè)遞增的子數(shù)列,且兩個(gè)子序列相連的邊界數(shù)字一定是遞減的,比如:{3,4,5} {1, 2}兩個(gè)遞增數(shù)列,5和1這兩個(gè)邊界是下降的,從而我們可以得到二分的條件,假設(shè):當(dāng)前位置為i,那么當(dāng)a[i-1] > a[i]時(shí), i就是最小的數(shù)。

public class Solution {
    public int minNumberInRotateArray(int [] array) {
        return binarySearch(array, 0, array.length-1);
    }
    /**
          大體上就是一個(gè)二分搜索,注意搜索條件即可
    */
    public int binarySearch(int[] arr, int l, int r) {
        
        if (arr[0] < arr[arr.length - 1])
            return arr[0];

        int mid = (l + r) / 2;
        // 這一句就是為了覆蓋數(shù)列數(shù)字全部相等的情況
        if(mid == r) return arr[r];
        if (arr[mid] < arr[mid - 1])
            return arr[mid];
        
        int res = 0;
        if(l <= r) {
            if (arr[mid] < arr[l])
                res = binarySearch(arr, l, mid);
            else
                res = binarySearch(arr, mid, r);
        }
        return res;
    }
}

第七題

大家都知道斐波那契數(shù)列,現(xiàn)在要求輸入一個(gè)整數(shù)n,請你輸出斐波那契數(shù)列的第n項(xiàng)。
n<=39
????這題沒啥好講的,為了避免爆棧,應(yīng)該采用迭代的方式。

public class Solution {
    public int Fibonacci(int n) {
        if(n == 0)
            return 0;
        if(n == 1)
            return 1;
         
        int count = 1;
        Queue<Integer> queue = new LinkedList<Integer>();
        queue.add(0);
        queue.add(1);
        int res = -1;
        while(count != n) {
            res = queue.poll() + queue.peek();
            queue.add(res);
            count++;
        }
        return res;
    }
}

第八題

一只青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個(gè)n級的臺階總共有多少種跳法。

????這題考察的就是一個(gè)遞推的是個(gè)思想。假設(shè)i表示青蛙要跳上的臺階,當(dāng)i==1時(shí),只有一種方法;當(dāng)i==2時(shí),可以從上一個(gè)臺階,或上上一個(gè)臺階跳上去,所有有兩種方式,從而可以知道,當(dāng)i > 1時(shí),res = step1 + step2(這里的step1和step2分別表示跳到上一個(gè)臺階和跳到上上一個(gè)臺階的跳法)。

public class Solution {
    public int JumpFloor(int target) {
        if(target == 1)
            return 1;
        if(target == 2)
            return 2;
        int result = 0;
        int step1 = 1, step2 = 1;
        target -= 1;
        while(target-- != 0) {
            result = step1 + step2;
            step1 = step2;
            step2 = result;
        }
        return result;
    }
}

第九題

一只青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個(gè)n級的臺階總共有多少種跳法。

????這道題,最簡單最快速的方法,就是直接用排列組合去做。把n個(gè)臺階分成1部分、2部分、3...n部分,c(N,0)+c(N,1)+...+C(N,N) = 2^N。

public class Solution {
    public int JumpFloorII(int target) {
        return (int)Math.pow(2, target-1);
    }
}

第十題

我們可以用21的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個(gè)21的小矩形無重疊地覆蓋一個(gè)2*n的大矩形,總共有多少種方法?

????這道題的思路其實(shí)和第八題非常類似,假設(shè)n=5,我們可以看成n=3和n=4兩種情況,但是注意:n=3時(shí),剩下2個(gè)小矩陣,所以還可以排成2種,但是有其中一種(豎著排列的)會(huì)與n=3時(shí)候的重復(fù),所以其實(shí)也只能排一種。所以我們可以知道:當(dāng) n==1時(shí) res = 1;當(dāng)n==2時(shí),res=2,當(dāng)n>2時(shí),res = cnt[n-1] + cnt[n-2]。

public class Solution {
    public int RectCover(int target) {
        if(target == 0)
            return 0;
            
        if(target == 1)
            return 1;
        
        if(target == 2)
            return 2;
        
        return RectCover(target-1) + RectCover(target-2);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,739評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,702評論 2 370