劍指offer中幾道算法題的思考

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

  • 假如二維數(shù)組為 {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};同時查找的值為15蜕衡。

    • 常規(guī)的思路為我們?nèi)〉矫總€二維數(shù)組的值,然后遍歷每個值设拟,判斷是否相等慨仿!同時我們知道會循環(huán)16次。代碼如下
        private boolean lookUpInTwoDimensionalArrays(int[][] a, int num) {
        // 至少保證 長度至少為1纳胧,且還有元素镰吆,
        if (a == null || a.length < 1 || a[0].length < 1) {
            return false;
        }
        int b = 0;
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[i].length; j++) {
                b++;
                if (num == a[i][j]) {
                    // 一共循環(huán)多少次:12
                    System.out.println(TAG + "一共循環(huán)多少次:" + b);
                    return true;
                }
            }
        }
        return false;
       }
      
    • 解題的思路如下
      • 1、選取二維數(shù)組的中的第一個元素跑慕,比較最右邊的值万皿,如果相等,就查找結(jié)束
      • 2核行、選取二維數(shù)組的中的第一個元素牢硅,比較最右邊的值,如果大于芝雪,查找的就是這個元素减余,同時角標(biāo)減去1,然后繼續(xù)查找
      • 3惩系、選取二維數(shù)組的中的第一個元素位岔,比較最右邊的值,如果大于堡牡,查找的不是這個元素抒抬,就去查找下一個數(shù)組,然后繼續(xù)查找
        二維數(shù)組的查找過程.png
  • 最終的代碼如下

 /**
     * 數(shù)組是遞增的 悴侵,從左到右  從上到下,那么數(shù)組一定是個正方形的樣子
     *
     * @param arr 原始的數(shù)組
     * @param num 需要查找的數(shù)字
     * @return 是否找到了
     */
    private boolean newLookUpInTwoDimensionalArrays(int[][] arr, int num) {
        if (arr == null || arr.length < 1 || arr[0].length < 1) {
            return false;
        }
        int rowTotal = arr.length;// 數(shù)組的行數(shù)
        int colTolal = arr[0].length;// 數(shù)組的列數(shù)
        //開始的角標(biāo)
        int row = 0;
        int col = colTolal - 1;
        int i = 0;
        while (row >= 0 && row < rowTotal && col >= 0 && col < colTolal) {
            // 是二維數(shù)組的 arr[0][arr[0].length-1] 的值瞧剖,就是最右邊的值
            i++;
            if (arr[row][col] == num) {
                System.out.println(TAG + "newLookUpInTwoDimensionalArrays 執(zhí)行了多少次" + i);
                return true;
            } else if (arr[row][col] > num) {// 如果找到的值 比目標(biāo)的值大的話,就把查找的列數(shù)減去1
                col--;//列數(shù)減去1 可免,代表向左移動
            } else {// 比目標(biāo)的num大的,就把行數(shù)加上1做粤,然后往下移動
                row++;
            }
        }
        return false;
    }
  • 如果查找的值為15浇借,那么舊的代碼會執(zhí)行15次,新的代碼只會執(zhí)行3次怕品。

2妇垢、請實現(xiàn)一個函數(shù),把字符串中的每個空格替換成"%20",例如“We are happy.”闯估,則輸出“We%20are%20happy.”.

  • 第一種方法:先判斷字符串中空格的數(shù)量灼舍。根據(jù)數(shù)量判斷該字符串有沒有足夠的空間替換成"%20"。如果有足夠空間涨薪,計算出需要的空間骑素。根據(jù)最終需要的總空間,維護一個指針在最后刚夺。從后到前献丑,遇到非空的就把該值挪到指針指向的位置,然后指針向前一位侠姑,遇到“ ”创橄,則指針前移,依次替換為“02%”莽红。
  public char[]  replaceBlank(char[] string, int usedLength) {
        // 判斷輸入是否合法
        System.out.println(TAG+"string.length="+string.length);
        System.out.println(TAG+"usedLength="+usedLength);
        if (string == null || string.length < usedLength) {
            return null;
        }

        // 統(tǒng)計字符數(shù)組中的空白字符數(shù)
        int whiteCount = 0;
        for (int i = 0; i < usedLength; i++) {
            if (string[i] == ' ') {
                whiteCount++;
            }
        }
        // 如果沒有空白字符就不用處理
        if (whiteCount == 0) {
            return string;
        }
        // 計算轉(zhuǎn)換后的字符長度是多少
        int targetLength = whiteCount * 2 + usedLength;
         //新的保存的字符串的數(shù)組
        char[] newChars = new char[targetLength];
        int tmp = targetLength; // 保存長度結(jié)果用于返回
//        if (targetLength > string.length) { // 如果轉(zhuǎn)換后的長度大于數(shù)組的最大長度妥畏,直接返回失敗
//            return -1;
//        }
        // todo  必須先做 這個,注意體會  --i  和 i-- 的區(qū)別
        usedLength--; // 從后向前安吁,第一個開始處理的字符
        targetLength--; // 處理后的字符放置的位置
        // 字符中有空白字符咖熟,一直處理到所有的空白字符處理完
        while (usedLength >= 0 && usedLength < targetLength) {
            // 如是當(dāng)前字符是空白字符,進行"%20"替換
            if (string[usedLength--] == ' ') {
                newChars[targetLength--] = '0';
                newChars[targetLength--] = '2';
                newChars[targetLength--] = '%';
            } else { // 否則移動字符
                newChars[targetLength--] = string[usedLength];
            }
            usedLength--;
        }
        return newChars;
    }
  • 第二種方法柳畔,非常的消耗時間和內(nèi)存馍管。
 private String idoWorkReplace(String str, String tagStr) {
        if (str == null || str.length() < 1) {
            return "";
        }
        String[] split = str.split(" ");
        StringBuffer stringBuffer = new StringBuffer();
        for (String s : split) {
            stringBuffer.append(s);
            stringBuffer.append(tagStr);
        }
        CharSequence charSequence = stringBuffer.subSequence(0, stringBuffer.length() - tagStr.length());
        return charSequence.toString();
    }
  • 第三種方法,調(diào)用replace方法薪韩,如果僅僅來講替換字符串的話确沸,是最好的方法,關(guān)鍵的方法是indexOf(this, targetStr, lastMatch).

 StringBuffer sb = new StringBuffer();
        sb.append(str);
        // todo  最節(jié)能的方法
        sb.toString().replace(" ", "%20");
  • 第四種方法和第一種方法異曲同工:先統(tǒng)計空白的數(shù)量俘陷,然后計算出有多少空白的長度罗捎,然后設(shè)置新的長度StringBuffer,通過插入最大角標(biāo)的地方拉盾,不斷的插入桨菜,就可以了
 private String replaceSpaces(String string) {
        //判斷是否 輸入合法
        if (string == null || string.length() < 1) {
            return "";
        }
        char[] chars = string.toCharArray();
        // 統(tǒng)計有多少的空白的數(shù)組
        int whiteCount = 0;
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == ' ') {
                whiteCount++;
            }
        }
        if (whiteCount == 0) {
            return string;
        }
        //最原本的長度
        int indexold = string.length() - 1;
        // 轉(zhuǎn)換完成后的長度
        int newlength = string.length() + whiteCount * 2;
        //新的長度
        int indexnew = newlength - 1;
        StringBuffer stringBuffer = new StringBuffer(string);
        //設(shè)置新的buffer的長度
        stringBuffer.setLength(newlength);
        for (; indexold >= 0 && indexold < newlength; indexold--) {
            // 原來的 字符串的最后一位為空格
            if (string.charAt(indexold) == ' ') {
                stringBuffer.setCharAt(indexnew--, '0');
                stringBuffer.setCharAt(indexnew--, '2');
                stringBuffer.setCharAt(indexnew--, '%');
            } else {//不為空的話,就直接放進去 就行了
                stringBuffer.setCharAt(indexnew--, string.charAt(indexold));
            }
        }
        return stringBuffer.toString();
    }

3捉偏、輸入個鏈表的頭結(jié)點倒得,從尾到頭反過來打印出每個結(jié)點的值。

  • 數(shù)據(jù)結(jié)構(gòu)
 public static class ListNode {
        int val;
        ListNode next;
        public ListNode(int  v){
            this.val=v;
        }
    }
  • 初始化
     ListNode listNode = new ListNode(10);
     ListNode listNode1 = new ListNode(11);
     ListNode listNode2 = new ListNode(12);
     ListNode listNode3 = new ListNode(13);
      ListNode listNode4 = new ListNode(14);
        listNode.next=listNode1;
        listNode1.next=listNode2;
        listNode2.next=listNode3;
        listNode3.next=listNode4;
  • 第一種方法的詳情,非常像二叉樹的遍歷夭禽,也是最簡單的方法霞掺。
   public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        arrayList.clear();
        if (listNode != null) {
            printListFromTailToHead(listNode.next);//指向下一個節(jié)點
            arrayList.add(listNode.val);//將當(dāng)前節(jié)點的值存到列表中
        }
        return arrayList;
    }
  • 第二種方法,利用Stack的特點,Stack類:繼承自Vector讹躯,實現(xiàn)一個后進先出的棧,不太明白的同學(xué)可以看這里常用集合的原理分析;
private static void doWhat(ListNode listNode) {
        Stack<ListNode> stack = new Stack<>();
        while (listNode!=null){
            stack.push(listNode);
            listNode=listNode.next;
        }
        System.out.println(" stack "+stack.size());
//        for (int i=0;i<stack.size();i++){
//            System.out.println("每個該打印的元素 ::"+stack.get(i).val);
//        }
        ListNode tmp;
        while (!stack.empty()){
            // 移除堆棧頂部的對象菩彬,并作為此函數(shù)的值返回該對象缠劝。
            tmp = stack.pop();
            System.out.println("tmp="+tmp.val);
          //  System.out.println("每個該打印的元素 :"+tmp.val);
        }
    }

4、輸入某二叉樹的前序遍歷和中序遍歷的結(jié)果骗灶,請重建出該二叉樹惨恭。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字。這個題的官方的答案耙旦,我本人持有嚴(yán)重的懷疑脱羡,也有可能是我根本沒有找到正確的答案!

  • 認(rèn)識下什么二叉樹:二叉樹是每個結(jié)點最多有兩個子樹的樹結(jié)構(gòu)母廷。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)轻黑。二叉樹常被用于實現(xiàn)二叉查找樹和二叉堆。樹的數(shù)據(jù)結(jié)構(gòu)能夠同時具備數(shù)組查找快的優(yōu)點以及鏈表插入和刪除快的優(yōu)點
  • 代碼結(jié)構(gòu)
public interface Tree {
    //查找節(jié)點
     Node find(int key);
    //插入新節(jié)點
     boolean insert(int data);
    //中序遍歷
     void infixOrder(Node current);
    //前序遍歷
     void preOrder(Node current);
    //后序遍歷
     void postOrder(Node current);
    //查找最大值
     Node findMax();
    //查找最小值
     Node findMin();
    //刪除節(jié)點
     boolean delete(int key);
}
  • Node
public class Node {
    int data;   //節(jié)點數(shù)據(jù)
    Node leftChild; //左子節(jié)點的引用
    Node rightChild; //右子節(jié)點的引用

    public Node(int data){
        this.data = data;
    }
    //打印節(jié)點內(nèi)容
    public void display(){
        System.out.println(data);
    }

    @Override
    public String toString() {
        return super.toString();
    }
}
  • 插入數(shù)據(jù)的過程
      BinaryTree bt = new BinaryTree();
       // 第一個插入的結(jié)點是 根節(jié)點
       bt.insert(50);
       bt.insert(20);
       bt.insert(80);
       bt.insert(10);
       bt.insert(30);
       bt.insert(60);
       bt.insert(90);
       bt.insert(25);
       bt.insert(85);
       bt.insert(100);
  • insert 代碼
//插入節(jié)點
    public boolean insert(int data) {
        Node newNode = new Node(data);
        if (root == null) {//當(dāng)前樹為空樹琴昆,沒有任何節(jié)點
            root = newNode;
            return true;
        } else {
            Node current = root;
            Node parentNode = null;
            while (current != null) {
                parentNode = current;
                if (current.data > newNode.data) {//當(dāng)前值比插入值大氓鄙,搜索左子節(jié)點
                    current = current.leftChild;
                    if (current == null) {//左子節(jié)點為空,直接將新值插入到該節(jié)點
                        parentNode.leftChild = newNode;
                        return true;
                    }
                } else {
                    current = current.rightChild;
                    if (current == null) {//右子節(jié)點為空业舍,直接將新值插入到該節(jié)點
                        parentNode.rightChild = newNode;
                        return true;
                    }
                }
            }
        }
        return false;
    }
二叉樹插入數(shù)據(jù)的過程.png
二叉樹最終的結(jié)構(gòu).png
  • 最終的圖解如下
二叉樹 insert 圖解.jpg
  • 二叉樹的前序遍歷:根節(jié)點>>左子樹>>右子樹
  public void preOrder(Node current) {
        if (current != null) {
            System.out.print(current.data + " ");
            infixOrder(current.leftChild);
            infixOrder(current.rightChild);
        }
    }
  • 1抖拦、根節(jié)點50,查找左節(jié)點舷暮,找到20态罪,然后找到10,輸出10下面,然后找到25 复颈,然后30 。到這里輸出的結(jié)果是 50 10 20 25 30
  • 2沥割、查找根節(jié)點的50的右節(jié)點耗啦,然后找出80,找出80的左節(jié)點60.接著80机杜,查找80的右節(jié)點95帜讲,輸出85 然后 90 ,最后輸出100
  • 3椒拗、最終的輸出的結(jié)果50 10 20 25 30 60 80 85 90 100
前序遍歷.png
  • 二叉樹中序遍歷:首先遍歷左子樹似将,然后訪問根結(jié)點,最后遍歷右子樹蚀苛。 左子樹 ---》根節(jié)點----》 右子樹
  public void infixOrder(Node current) {
        if (current != null) {
            infixOrder(current.leftChild);
            System.out.print(current.data + " ");
            infixOrder(current.rightChild);
        }
    }
  • 1在验、傳入根節(jié)點 值為50 ,查找50的左節(jié)點為20不為null枉阵,再次查找20的左節(jié)點译红,為10,也不為null兴溜,然后在查找10的左節(jié)點侦厚,為null ,輸出10拙徽,第一個節(jié)點輸出完成為 10
  • 2刨沦、接下來,查找的10的右節(jié)點膘怕,為null想诅,不進入輸出語句
  • 3、這下輸出語句20岛心,查找20右節(jié)點来破,查找到值為30,第一步查找的值為左節(jié)點忘古,查找到的值為25徘禁,查找右節(jié)點為null
  • 4、到這里輸出的結(jié)果為 10 20 25 30
  • 5髓堪、這樣子50左節(jié)點就全部查找完了
  • 6送朱、接下來查找50的右節(jié)點,查找右節(jié)點80干旁,然后查找80的左節(jié)點驶沼,查找到的值為60,60沒有右節(jié)點,繼續(xù)查找80的右節(jié)點争群,到這里 輸出的結(jié)果10 20 25 30 50 60 80
  • 7回怜、查找80右節(jié)點,查到到值為90换薄,接著查找90的左節(jié)點玉雾,查到到的值85,接著85的左右節(jié)點為null专控,返回直接查找90的右節(jié)點抹凳,查找到了100,
  • 8伦腐、最終輸出的結(jié)果赢底,10 20 25 30 50 60 80 85 90 100
二叉樹的中序遍歷.png
  • 后序遍歷:在二叉樹中,先左后右再根柏蘑,即首先遍歷左子樹幸冻,然后遍歷右子樹,最后訪問根結(jié)點咳焚。
    • 1洽损、根節(jié)點50,查找左節(jié)點20革半,在繼續(xù)查找20的左節(jié)點10,10沒有左右節(jié)點碑定,打印10,然后查找到20的右節(jié)點30,30繼續(xù)查找到25流码,第一次輸出為 10 20 25 30
    • 2、最終輸出10 20 25 30 60 80 85 90 100 50
二叉樹的后序遍歷.png
  • 查找最大值或者是最小值
 //找到最大值
    public Node findMax() {
        Node current = root;
        Node maxNode = current;
        while (current != null) {
            maxNode = current;
            current = current.rightChild;
        }
        return maxNode;
    }

    //找到最小值
    public Node findMin() {
        Node current = root;
        Node minNode = current;
        while (current != null) {
            minNode = current;
            current = current.leftChild;
        }
        return minNode;
    }
  • 例如:前序遍歷序列{50 10 20 25 30 60 80 85 90 100}和中序遍歷序列{10 20 25 30 50 60 80 85 90 100}延刘, 重建二叉樹并輸出它的頭結(jié)點漫试。
  • 原始節(jié)點的遍歷結(jié)果,可以很清楚的看到,有多少左右節(jié)點碘赖,那個節(jié)點是那個的節(jié)點等等的信息驾荣。
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node50  是那邊啊 根
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node20  是那邊啊 左
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node10  是那邊啊 左
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node30  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node25  是那邊啊 左
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node80  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node60  是那邊啊 左
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node90  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node85  是那邊啊 左
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node100  是那邊啊 右
  • 解決方法一:
 public static Node reConstructBinaryTree(int[] pre, int[] in) {
        if (pre == null || in == null || pre.length != in.length)//如果先序或者中序數(shù)組有一個為空的話,就無法建樹普泡,返回為空
            return null;
        else {
            return reBulidTree(pre, 0, pre.length - 1, in, 0, in.length - 1);
        }
    }

    /**
     * @param pre
     * @param startPre
     * @param endPre
     * @param in
     * @param startIn
     * @param endIn
     * @return
     */
    private static Node reBulidTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) {
        if (startPre > endPre || startIn > endIn)//先對傳的參數(shù)進行檢查判斷
            return null;
        int root = pre[startPre];//數(shù)組的開始位置的元素是跟元素
        int locateRoot = locate(root, in, startIn, endIn);//得到根節(jié)點在中序數(shù)組中的位置 左子樹的中序和右子樹的中序以根節(jié)點位置為界

        if (locateRoot == -1) //在中序數(shù)組中沒有找到跟節(jié)點播掷,則返回空
            return null;
        Node treeRoot = new Node(root);//創(chuàng)建樹根節(jié)點
        treeRoot.leftChild = reBulidTree(pre, startPre + 1, startPre + locateRoot - startIn, in, startIn, locateRoot - 1);//遞歸構(gòu)建左子樹
        treeRoot.rightChild = reBulidTree(pre, startPre + locateRoot - startIn + 1, endPre, in, locateRoot + 1, endIn);//遞歸構(gòu)建右子樹
        return treeRoot;
    }

    //找到根節(jié)點在中序數(shù)組中的位置,根節(jié)點之前的是左子樹的中序數(shù)組撼班,根節(jié)點之后的是右子樹的中序數(shù)組
    private static int locate(int root, int[] in, int startIn, int endIn) {
        for (int i = startIn; i < endIn; i++) {
            if (root == in[i])
                return i;
        }
        return -1;
    }

  • 但是這個的輸出結(jié)果如下歧匈,很明顯沒有重建二叉樹成功,它的執(zhí)行流程如上面的代碼权烧,由于個人認(rèn)為沒有重建眯亦,所以就沒有輸出示意圖
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 新新----的中序遍歷的開始
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node50  是那邊啊 根
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node10  是那邊啊 左
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node20  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node25  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node60  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node80  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node85  是那邊啊 右
09-02 05:51:53.177 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node90  是那邊啊 右
09-02 05:51:53.185 2590-2590/com.android.interview I/System.out: 新新----的中序遍歷的結(jié)束
  • 解決方法二:解題思路也是不斷地遍歷,代碼如下
 public static Node reConstructBinaryTreeNew(int[] pre, int[] in) {
        if (pre.length == 0 || in.length == 0)
            return null;
         Node node = new Node(pre[0]);
        for (int i = 0; i < pre.length; i++) {
            if (pre[0] == in[i]) {
                node.leftChild = reConstructBinaryTreeNew(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
                node.rightChild = reConstructBinaryTreeNew(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
                break;
            }
        }
        return node;
    }
  • 輸出的結(jié)果和方法一的結(jié)果是一樣的般码。二叉樹的結(jié)果還是不一樣妻率。
09-02 05:51:53.185 2590-2590/com.android.interview I/System.out: 新新----的中序遍歷的開始------------
09-02 05:51:53.185 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node50  是那邊啊 根
09-02 05:51:53.185 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node10  是那邊啊 左
09-02 05:51:53.186 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node20  是那邊啊 右
09-02 05:51:53.194 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node25  是那邊啊 右
09-02 05:51:53.211 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node30  是那邊啊 右
09-02 05:51:53.212 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node60  是那邊啊 右
09-02 05:51:53.212 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node80  是那邊啊 右
09-02 05:51:53.212 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node85  是那邊啊 右
09-02 05:51:53.213 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node90  是那邊啊 右
09-02 05:51:53.213 2590-2590/com.android.interview I/System.out: 這個值是什么啊 Node100  是那邊啊 右
09-02 05:51:53.214 2590-2590/com.android.interview I/System.out: 新新----的中序遍歷的結(jié)束------------
  • 解決方法三:由前序遍歷的第一個節(jié)點可知根節(jié)點。根據(jù)根節(jié)點板祝,可以將中序遍歷劃分成左右子樹宫静。在前序遍歷中找出對應(yīng)的左右子樹,其第一個節(jié)點便是根節(jié)點的左右子節(jié)點券时。按照上述方式遞歸便可重建二叉樹孤里。

  • 這三種的方式的結(jié)果也是一樣的,我自己認(rèn)為二叉樹沒有重構(gòu)成功橘洞,如果有大佬明白的捌袜,可以指點下,謝謝了!

  • 謝謝以下資料給與我的幫助

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炸枣,一起剝皮案震驚了整個濱河市虏等,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌适肠,老刑警劉巖霍衫,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異侯养,居然都是意外死亡敦跌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門逛揩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柠傍,“玉大人麸俘,你說我怎么就攤上這事⌒” “怎么了疾掰?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵搂誉,是天一觀的道長徐紧。 經(jīng)常有香客問我,道長炭懊,這世上最難降的妖魔是什么并级? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮侮腹,結(jié)果婚禮上嘲碧,老公的妹妹穿的比我還像新娘。我一直安慰自己父阻,他們只是感情好愈涩,可當(dāng)我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著加矛,像睡著了一般履婉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斟览,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天毁腿,我揣著相機與錄音,去河邊找鬼苛茂。 笑死已烤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的妓羊。 我是一名探鬼主播胯究,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼躁绸!你這毒婦竟也來了裕循?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤涨颜,失蹤者是張志新(化名)和其女友劉穎费韭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庭瑰,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡星持,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了弹灭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片督暂。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡揪垄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逻翁,到底是詐尸還是另有隱情饥努,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布八回,位于F島的核電站酷愧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏缠诅。R本人自食惡果不足惜溶浴,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望管引。 院中可真熱鬧士败,春花似錦、人聲如沸褥伴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽重慢。三九已至饥臂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伤锚,已是汗流浹背擅笔。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留屯援,地道東北人猛们。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像狞洋,于是被迫代替她去往敵國和親弯淘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,974評論 2 355

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