劍指

1. 二維數(shù)組中查找

在一個(gè)二維數(shù)組中(每個(gè)一維數(shù)組的長度相同)疾就,每一行都按照從左到右遞增的順序排序肩碟,每一列都按照從上到下遞增的順序排序贸辈。請(qǐng)完成一個(gè)函數(shù)纳决,輸入這樣的一個(gè)二維數(shù)組和一個(gè)整數(shù)碰逸,判斷數(shù)組中是否含有該整數(shù)

思路
選擇該二維數(shù)組的最右上角的那個(gè)數(shù)開始掃描,當(dāng)target小于該值時(shí)阔加,可以清除一列饵史,當(dāng)target大于該值時(shí),可以清除一行

public class Solution {
    public boolean Find(int target, int [][] array) {
        if (null == array) {
            return false;
        }
        int i = 0;//表示第一行
        int j = array[0].length;//表示該二維數(shù)組的列數(shù)
        int start;
        while (i < array.length && j > 0) {
            start = array[i][j-1];//每次清除一行或一列后的最右上角的元素
            if (target < start) {
                j--;
            } else if (target > start) {
                i++;
            } else {
                return true;
            }
        }
        return false;
    }
}

2. 替換空格

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

思路

  1. 將每個(gè)空格替換成“%20”厌蔽,則相當(dāng)于每一個(gè)空格都需要新加兩個(gè)字符的位置;如果考慮輸入的是一個(gè)數(shù)組摔癣,為了能夠讓每個(gè)字符只移動(dòng)一次奴饮,則可以預(yù)先預(yù)留出來足夠的正合適的空間纬向,
  2. 同時(shí)用兩個(gè)指針從分別從舊的末尾和新的末尾開始向前遍歷,可做到每個(gè)字符只移動(dòng)一次
public class Solution {
    public String replaceSpace(StringBuffer str) {
        if (null == str || str.length() == 0) {
            return "";
        }
        int strOldLength = str.length();//最開始的字符串長度
        int blankNumber = 0;//記錄空白字符的個(gè)數(shù)
        for (int i = 0; i < strOldLength; i++) {
            if (' ' == str.charAt(i)) {
                ++blankNumber;
                // 每遇到一個(gè)空格戴卜,StringBuffer都在末尾新增兩個(gè)空的位置
                str.append(' ').append(' ');
            }
        }
        // 如果掃描完字符串的數(shù)組沒有發(fā)現(xiàn)空格逾条,則直接返回
        if (0 == blankNumber) {
            return str.toString();
        }
 
        int strNewLength = str.length();
        int firstPoint = strOldLength-1;  // 舊的末尾索引
        int lastPoint = strNewLength-1;  // 新的末尾索引
        // 當(dāng)所有的空格都替換后,兩個(gè)節(jié)點(diǎn)會(huì)相遇
        while (firstPoint >= 0 && lastPoint > firstPoint) {
            if (' ' ==  str.charAt(firstPoint)) {
                str.setCharAt(lastPoint--, '0');  // 設(shè)置當(dāng)前索引位置的值為0投剥,通過指針
                str.setCharAt(lastPoint--, '2');
                str.setCharAt(lastPoint--, '%');
            } else {
                str.setCharAt(lastPoint--, str.charAt(firstPoint));
            }
            firstPoint--;
        }
        return str.toString();
    }
}

3. 從尾到頭打印鏈表

輸入一個(gè)鏈表师脂,按鏈表值從尾到頭的順序返回一個(gè)ArrayList。

思路
有多種解答方案:1江锨,遞歸(本博客列出的代碼實(shí)例) 2吃警,棧 3,倒轉(zhuǎn)鏈表指針啄育,再從頭到尾打印

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {//該思路是采用遞歸酌心,從尾到頭依次打印鏈表節(jié)點(diǎn)
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList arrayList = new ArrayList();
        if (listNode == null) {
            return arrayList;
        }
        printListFromTailToHead(arrayList, listNode);
        return arrayList;
    }
    
    public void printListFromTailToHead(ArrayList array, ListNode listNode) {
        
        
        if (listNode.next == null) {//當(dāng)?shù)竭_(dá)鏈表尾部時(shí),將值添加到ArrayList
            array.add(listNode.val);
        }else {
            printListFromTailToHead(array, listNode.next);//進(jìn)入下一個(gè)節(jié)點(diǎn)
            array.add(listNode.val);//自己的下一個(gè)節(jié)點(diǎn)執(zhí)行完挑豌,回退到本節(jié)點(diǎn)時(shí)再將值添加進(jìn)ArrayList
        }
    }

4. 重建二叉樹

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

思路
二叉樹的前序序列中第一個(gè)節(jié)點(diǎn)永遠(yuǎn)是根節(jié)點(diǎn)root铝阐,中序序列中root所在的位置的左邊序列址貌,都是當(dāng)前root節(jié)點(diǎn)的左子樹,右邊都是root節(jié)點(diǎn)的右子樹饰迹,
因此芳誓,前序序列的root節(jié)點(diǎn)的下一位又是它的左子樹的根節(jié)點(diǎn),同樣的規(guī)則適用于它的左右子樹啊鸭,所以這里我們可以用遞歸來實(shí)現(xiàn)

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        // 如果數(shù)組為空或者兩個(gè)數(shù)組的長度不一致锹淌,則輸入有誤
        if (pre == null || in == null || pre.length < 0 || in.length < 0 || pre.length != in.length) {
            System.out.println("數(shù)組不能為空或者兩個(gè)數(shù)組長度不一致");
            return null;
        }
        // 之所以需要四個(gè)位置變量,是因?yàn)樾枰涗浨靶蛐蛄械拈_始和結(jié)束位置赠制,也要記錄
        return reConstructBinaryTree(pre, in, 0, pre.length-1, 0, in.length-1);
        // 中序序列的開始和結(jié)束位置
    }
    // fStart表示前序序列開始節(jié)點(diǎn)赂摆, fStop表示前序序列結(jié)束節(jié)點(diǎn),mStart表示中序序列開始節(jié)點(diǎn)钟些,mStop表示中序序列結(jié)束節(jié)點(diǎn)
    public TreeNode reConstructBinaryTree(int [] pre, int [] in, int fStart, int fStop, int mStart, int mStop) {
 
        int rootValue = pre[fStart];
        TreeNode root = new TreeNode(rootValue);//先創(chuàng)建根節(jié)點(diǎn)
        root.left = null;
        root.right = null;
        //判斷是否是只有一個(gè)節(jié)點(diǎn)
        if (fStart == fStop) {
            if (mStart == mStop) {
                return root;
            }else { //其實(shí)上面做了判斷烟号,這里就不會(huì)走到else子句中來
                System.out.println("兩個(gè)數(shù)組輸入有誤");
                return null;
            }
        }
        int mm = mStart; //用一個(gè)變量記錄二叉樹的root節(jié)點(diǎn)在中序序列中的位置
        //直到在中序序列中找到root,或者遍歷完中序序列數(shù)組
        while (in[mm] != rootValue && mm <= mStop) {
            ++mm;
        }
        //此時(shí)還不相等的話政恍,說明中序序列中沒有此時(shí)的root
        if (in[mm] != rootValue) {
            System.out.println("中序序列中沒有與前序序列中確定的root節(jié)點(diǎn)相等的節(jié)點(diǎn)值");
            return null;
        }
        //這里一定要這樣寫汪拥,記錄移動(dòng)的位置
        int mLengh = mm - mStart;
        //前序序列當(dāng)前的樹開始的節(jié)點(diǎn)位置+移動(dòng)的位置就等于當(dāng)前樹的子樹的結(jié)束位置
        int fLeftSubTreeStop = fStart + mLengh;
 
        if (mm > mStart) {
            root.left = reConstructBinaryTree(pre, in, fStart+1, fLeftSubTreeStop, mStart, mm-1);
            //(前序序列數(shù)組,中序序列數(shù)組篙耗,前序序列當(dāng)前樹開始節(jié)點(diǎn)的后一位迫筑,
            //前序序列當(dāng)前樹的子樹結(jié)束的位置宪赶,中序序列當(dāng)前樹開始的位置,中序序列root位置的前一位)
        }
        if (mm < mStop) {  
            root.right = reConstructBinaryTree(pre, in, fLeftSubTreeStop+1, fStop, mm+1, mStop);
            //(前序序列數(shù)組脯燃,中序序列數(shù)組搂妻,前序序列當(dāng)前樹的子樹結(jié)束的位置的前一位,
            //前序序列中當(dāng)前樹結(jié)束的位置辕棚,中序序列root位置的后一位欲主,中序序列中當(dāng)前樹結(jié)束的位置
        }
        return root;
    }
}

5. 用兩個(gè)棧實(shí)現(xiàn)隊(duì)列

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

思路

  1. 將stack1當(dāng)做入隊(duì)列,將stack2當(dāng)做出隊(duì)列补君,當(dāng)隊(duì)列需要push入隊(duì)列一個(gè)元素的時(shí)候涤妒,直接push到stack1就可以了;當(dāng)隊(duì)列需要pop出隊(duì)列時(shí)
  2. 首先判斷stack2是否為空赚哗,如果為空,則將stack1中的元素全部pop出來并依次push到stack2中硅堆,再讓stack2來pop一下就可以了屿储;如果不為空,stack2直接pop一下就行渐逃。

import java.util.Stack;
 
public class Solution {//思路:將stack1當(dāng)做入隊(duì)列够掠,將stack2當(dāng)做出隊(duì)列,當(dāng)隊(duì)列需要push入隊(duì)列一個(gè)元素的時(shí)候茄菊,直接push到stack1就可以了疯潭;當(dāng)隊(duì)列需要pop出隊(duì)列時(shí)
    //,首先判斷stack2是否為空面殖,如果為空竖哩,則將stack1中的元素全部pop出來并依次push到stack2中,再讓stack2來pop一下就可以了脊僚;如果不為空相叁,stack2直接pop一下就行。
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        if (stack2.size() == 0) {
            while (!stack1.empty()) {
                stack2.push(stack1.pop());
            }
        }
        if (stack2.size() == 0) {//當(dāng)stack1和stack2都長度為0的時(shí)候辽幌,運(yùn)行到這里還是會(huì)出現(xiàn)stack2的長度為0增淹,所以要做異常處理
            System.out.println("stack1和stack2的長度都為0,不能進(jìn)行pop操作乌企,拋出異常");
            return -1;
        }
        return stack2.pop();
    }
}

6. 旋轉(zhuǎn)數(shù)組的最小數(shù)字

把一個(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荣病,請(qǐng)返回0。

思路:對(duì)一個(gè)n長度的非減排序數(shù)組進(jìn)行旋轉(zhuǎn)有兩種情況:

  • 第一:旋轉(zhuǎn)了1~n-1個(gè)數(shù)字渗柿,會(huì)形成兩個(gè)非減排序的子數(shù)組个盆,如: 4 5 和 1 2 3;它的最小值是在第二個(gè)子數(shù)組的開頭朵栖,同時(shí)颊亮,第一個(gè)子數(shù)組的所有元素都大于或者等于第二個(gè)子數(shù)組,可以利用二分查找法來處理陨溅;
  • 第二:旋轉(zhuǎn)了0個(gè)數(shù)字终惑,得到的旋轉(zhuǎn)數(shù)組仍然是原數(shù)組:1 2 3 4 5,最小值就是第一個(gè)元素

注意:第二種情況里面:當(dāng)數(shù)組頭節(jié)點(diǎn)=尾節(jié)點(diǎn)=中間節(jié)點(diǎn)的時(shí)候门扇,無法用二分查找來縮小查找范圍雹有,如:0 1 1 1 1 1 ,旋轉(zhuǎn) 0 1 1 1 1變成:1 0 1 1 1 1,臼寄,只能用順序查找

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if (null == array || array.length == 0) {
            return 0;
        }
        int n = array.length - 1;
        int first = 0;//二分查找的開頭元素位置索引
        int min = first;//用一個(gè)新的元素記錄最小值霸奕,是為了方便如果是第二種情況,就不需要循環(huán)直接返回首節(jié)點(diǎn)
        int last = n-1;//二分查找的末尾元素位置索引
        int middle = 0;//中間節(jié)點(diǎn)位置索引
        while (array[first] >= array[last]) {//當(dāng)數(shù)組的開頭節(jié)點(diǎn)大于等于數(shù)組的末尾節(jié)點(diǎn)時(shí)吉拳,需要進(jìn)行循環(huán)判斷
            if (last - first == 1) {//當(dāng)二分查找的結(jié)束索引與開始索引之間相鄰的時(shí)候质帅,說明就找到了最小元素,
                //而且最小元素是結(jié)束索引上的元素(因?yàn)閒irst指針總會(huì)指向第一個(gè)子數(shù)組留攒,而第二個(gè)子數(shù)組總會(huì)指向第二個(gè)子數(shù)組)
                min = last;
                break;
            }
            middle = first + (last-first)/2;
            if (array[first] == array[middle] && array[middle] == array[last]) {//此時(shí)無法用二分查找
                // return 煤惩。。炼邀。
                //此處省略順序查找的方法
            }
            if (array[middle] >= array[first]) {//當(dāng)中間元素大于等于二分查找數(shù)組的開頭元素時(shí)魄揉,說明中間元素落在了第一個(gè)子數(shù)組中,最小元素要去后面找
                first = middle;
            }else if (array[middle] <= array[last]) {//否則當(dāng)中間元素小于等于二分查找數(shù)組的末尾元素時(shí)汤善,說明中間元素落在了第二個(gè)子數(shù)組中什猖,最小元素去前面找
                last = middle;
            }
        }
        //如果數(shù)組的第一個(gè)元素小于最后一個(gè)元素,說明:非減排序的數(shù)組的旋轉(zhuǎn)數(shù)組是它本身:1 2 3 4 5红淡,這時(shí)第一個(gè)元素就是最小元素
        return array[min];
    }
}

7.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末不狮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子在旱,更是在濱河造成了極大的恐慌摇零,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桶蝎,死亡現(xiàn)場(chǎng)離奇詭異驻仅,居然都是意外死亡谅畅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門噪服,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毡泻,“玉大人,你說我怎么就攤上這事粘优〕鹞叮” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵雹顺,是天一觀的道長丹墨。 經(jīng)常有香客問我,道長嬉愧,這世上最難降的妖魔是什么贩挣? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮没酣,結(jié)果婚禮上王财,老公的妹妹穿的比我還像新娘。我一直安慰自己裕便,他們只是感情好搪搏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著闪金,像睡著了一般。 火紅的嫁衣襯著肌膚如雪论颅。 梳的紋絲不亂的頭發(fā)上哎垦,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音恃疯,去河邊找鬼漏设。 笑死,一個(gè)胖子當(dāng)著我的面吹牛今妄,可吹牛的內(nèi)容都是我干的郑口。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盾鳞,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼犬性!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腾仅,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤乒裆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后推励,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹤耍,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肉迫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稿黄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喊衫。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖杆怕,靈堂內(nèi)的尸體忽然破棺而出族购,到底是詐尸還是另有隱情,我是刑警寧澤财著,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布联四,位于F島的核電站,受9級(jí)特大地震影響撑教,放射性物質(zhì)發(fā)生泄漏朝墩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一伟姐、第九天 我趴在偏房一處隱蔽的房頂上張望收苏。 院中可真熱鬧,春花似錦愤兵、人聲如沸鹿霸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懦鼠。三九已至,卻和暖如春屹堰,著一層夾襖步出監(jiān)牢的瞬間肛冶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國打工扯键, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睦袖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓荣刑,卻偏偏與公主長得像馅笙,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子厉亏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 2. 實(shí)現(xiàn) Singleton 3. 數(shù)組中重復(fù)的數(shù)字 4. 二維數(shù)組中的查找 5. 替換空格 6. 從尾到...
    Observer_____閱讀 2,930評(píng)論 0 1
  • 1.二維數(shù)組中的查找 題目描述在一個(gè)二維數(shù)組中(每個(gè)一維數(shù)組的長度相同)董习,每一行都按照從左到右遞增的順序排序,每一...
    雅芳閱讀 393評(píng)論 0 0
  • 下面是我整理的爱只,劍指Offer前五章所有的題目以及相關(guān)題和拓展題的題目和答案阱飘。代碼的話放在github上,您可以下...
    kikido閱讀 1,044評(píng)論 0 1
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書筆記,整理的知識(shí)點(diǎn)沥匈,也是為了防止忘記蔗喂,尊重勞動(dòng)成果,轉(zhuǎn)載注明出處哦高帖!如果你也喜歡缰儿,那...
    波波波先森閱讀 4,105評(píng)論 0 23
  • 說明: 本文中出現(xiàn)的所有算法題皆來自牛客網(wǎng)-劍指Offer在線編程題散址,在此只是作為轉(zhuǎn)載和記錄乖阵,用于本人學(xué)習(xí)使用,不...
    秋意思寒閱讀 1,154評(píng)論 1 1