藍橋杯練習題庫——試題 算法訓練 繪制地圖(二分法遞歸求解)


題目:

試題 算法訓練 繪制地圖

 

資源限制
時間限制:1.0s   內存限制:256.0MB
問題描述
  最近,WYF正准備參觀他的點卡工廠。WYF集團的經理氰垃圾需要幫助WYF設計參“觀”路線。現在,氰垃圾知道一下幾件事情:
  1.WYF的點卡工廠構成一顆二叉樹。
  2.一共有n座工廠。
  3.他需要把這顆樹上的點以后序遍歷的方法列出來,才能繪制地圖。
  還好,最近他的屬下給了他先序遍歷和中序遍歷的數據。可是,氰垃圾最近還要幫㊎澤穻解決一些問題,沒有時間。請你幫幫他,替他完成這項任務。由於氰垃圾的一些特殊的要求,WYF的參觀路線將會是這棵樹的后序遍歷。
輸入格式
  第一行一個整數n,表示一共又n座工廠。
  第二行n個整數,表示先序遍歷。
  第三行n個整數,表示中序遍歷。
輸出格式
  輸出共一行,包含n個整數,為后序遍歷。
樣例輸入
8
1 2 4 5 7 3 6 8
4 2 7 5 1 8 6 3
樣例輸出
4 7 5 2 8 6 3 1
數據規模和約定
  0<n<100000,。保證先序遍歷和中序遍歷合法,且均為1~n。
 
Java代碼:
package com.lzp.algorithmpractice.p13;

import java.util.Scanner;

/**
 * @Author LZP
 * @Date 2021/3/11 13:36
 * @Version 1.0
 *
試題 算法訓練 繪制地圖


資源限制
時間限制:1.0s   內存限制:256.0MB
問題描述
  最近,WYF正准備參觀他的點卡工廠。WYF集團的經理氰垃圾需要幫助WYF設計參“觀”路線。現在,氰垃圾知道一下幾件事情:
  1.WYF的點卡工廠構成一顆二叉樹。
  2.一共有n座工廠。
  3.他需要把這顆樹上的點以后序遍歷的方法列出來,才能繪制地圖。
  還好,最近他的屬下給了他先序遍歷和中序遍歷的數據。可是,氰垃圾最近還要幫㊎澤穻解決一些問題,沒有時間。請你幫幫他,替他完成這項任務。由於氰垃圾的一些特殊的要求,WYF的參觀路線將會是這棵樹的后序遍歷。
輸入格式
  第一行一個整數n,表示一共又n座工廠。
  第二行n個整數,表示先序遍歷。
  第三行n個整數,表示中序遍歷。
輸出格式
  輸出共一行,包含n個整數,為后序遍歷。
樣例輸入
8
1 2 4 5 7 3 6 8
4 2 7 5 1 8 6 3
樣例輸出
4 7 5 2 8 6 3 1
數據規模和約定
  0<n<100000,。保證先序遍歷和中序遍歷合法,且均為1~n。

 采用二分策略,遞歸求解
 */
public class Main {

    private static int[] front;
    private static int[] mid;
    private static int[] dp = new int[100000 + 10];
    private static int n;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        n = input.nextInt();
        front = new int[n];
        mid = new int[n];   

        for (int i = 0; i < n; i++) {
            front[i] = input.nextInt();
        }
        for (int i = 0; i < n; i++) {
            int temp = input.nextInt();
            mid[i] = temp;
            /*
                dp數組在這里的作用就是記錄中序遍歷序列中數的索引值,方
                便后面直接通過數組下標獲取,不用每一次都要為了拿一個數
                據而去遍歷整個中序遍歷序列
             */
            dp[temp] = i;
        }

        f();
    }

    public static void f() {
        Node tree = division(dp[front[0]], 0, 0, n - 1);
        laterAccess(tree);
    }

    /**
     * 遞歸
     * 這里的parent是為了找到根節點在中序遍歷序列中的索引,cur是在當前前序遍歷中指針指向的位置,
     * 它的傳入是在遞歸的過程中為了方便找左右孩子,start、end是兩個邊界的索引
     * @param parent
     * @param cur
     * @param start
     * @param end
     * @return
     */
    public static Node division(int parent, int cur, int start, int end) {
        // 遞歸的出口
        if (start == end) {
            return new Node(mid[parent], null, null);
        }

        if (start > end) {
            return null;
        }

        Node left = null;
        Node right = null;
        if (cur + 1 >= 0) {
            // 找左孩子
            left = division(dp[front[cur + 1]], cur + 1, start, parent - 1);
        }
        if (cur + 1 + (parent - start) < n) {
            // 找右孩子
            right = division(dp[front[cur + 1 + (parent - start)]], cur + 1 + (parent - start), parent + 1, end);
        }
        // 創建並返回父親節點
        return new Node(mid[parent], left, right);
    }

    /**
     * 后序遍歷
     * @param tree 樹的根節點
     */
    public static void laterAccess(Node tree) {
        if (tree != null) {
            laterAccess(tree.left);
            laterAccess(tree.right);
            System.out.print(tree.data + " ");
        }
    }
}

class Node {
    int data;
    Node left;
    Node right;
    public Node(int data, Node left, Node right) {
        this.data = data;
        this.left = left;
        this.right = right;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM