日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

用任意合法序列建立一棵二叉树(洛谷P1305题题解,Java语言描述)

發(fā)布時間:2025/3/15 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用任意合法序列建立一棵二叉树(洛谷P1305题题解,Java语言描述) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

這題是極其麻煩極其麻煩的一道題(前提是你不知道它有套路)……
我們不講那些歪門邪道,我們正兒八經(jīng)的解一下,想正經(jīng)求解,很麻煩很麻煩。。。

題目要求

P1305題題解

分析

這題你看著容易,那是你想當(dāng)然認(rèn)為建立一棵樹,給你的序列就是先根的,其實真實情況里不一定是……(當(dāng)然本題是,所以是橙題……)

這題肝的我簡直要暴斃,要多麻煩有多麻煩,大家如果有改進(jìn)策略請告訴我,我會虛心接受了。。。寫這么長代碼累死人啦!!

我講講我分析的思路吧:

我們要自己編寫結(jié)點類,其實結(jié)點湊起來就是tree,我們控一下root就可以咯。
手寫Node,由于指定類型,所以不加泛型,不加setter、getter,玩最簡單的版本:

static class Node {char data;Node left, right;Node(char data) {this.data = data;this.left = null;this.right = null;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Node node = (Node) o;return data == node.data;}@Overridepublic int hashCode() {return Objects.hash(data);}}

對咯,這個必須是(靜態(tài))內(nèi)部類,因為luoguOJ不識別,你寫成另一個class會判CE的。。。。。。靜態(tài)的內(nèi)部類是OK的,因為靜態(tài)不能訪問非靜態(tài)的,這會給方法里的調(diào)用帶來麻煩。
還有就是一定要重寫hashCode()和equals(),我們可是需要用data來區(qū)別Node的呀!!

首先我們建立一棵樹,需要建立臨時根結(jié)點,由于我們想知道這個結(jié)點是否已經(jīng)在樹里面,我們不想再次遍歷,那我們可以建立一個HashMap,存儲已經(jīng)加入樹中的結(jié)點。
我們還需要一個HashMap,用來為未插入樹中的結(jié)點提供查找的便利。

將初始化的根結(jié)點保存為根結(jié)點,左右兒子加上去。不過這個題無論何時都要注意 ‘*’ 的存在,必須不能插入data為 ‘*’ 的結(jié)點。

接下來開循環(huán),每次讀一行數(shù)據(jù),然后切成三份(toCharArray()),用三個char存儲。
循環(huán)里面先看看這個臨時的根結(jié)點是不是在map里,如果有就說明它在樹里,它不可能還有左右兒子,所以肯定是原先作為某個子結(jié)點的,進(jìn)行一下替換。
如果不在map里,就去unAddedMap里找,這里有的話思路同上,只不過這是一群沒加入樹里的臨時樹,相當(dāng)于與真正的樹構(gòu)成了一個森林而已……
如果都不在,那好,這就是沒有出現(xiàn)過的結(jié)點,我們看看它是不是新的根結(jié)點,這個判斷要用臨時根結(jié)點的左右兒子分別與當(dāng)前真實根節(jié)點比較,如果equals就換根,注意換根以后要查右兒子在不在unAddedMap里(肯定不在map里)。。如果不是換根的情況那就只能把它塞進(jìn)unAddedMap里了,畢竟這在當(dāng)前是一棵 “孤兒樹”,無依無靠嗚嗚嗚~~

大致是這樣,具體的看我代碼注釋吧,能看完說明你是個狠人,哦不,狼人(比狠人還狠一、)。。。

哦哦哦,差點忘說了,這個算法有一部分的邏輯是這樣的:
畢竟我們這個森林是需要合并的,當(dāng)合并的時候呢,就要把unAddedMap里的那個結(jié)點換掉臨時結(jié)點(未來的老祖宗——新根)的某個兒子(我WA的那次就是因為這個原因,太難了),然后在unAddedMap里遞歸刪除,在map里遞歸插入。。。。

這需要兩個static的輔助方法(private即可),很nice!!!

遞歸刪除

private static void deleteRecursively(Node root, Map<Character, Node> unAddedMap) {if (root == null) {return;}unAddedMap.remove(root.data);deleteRecursively(root.left, unAddedMap);deleteRecursively(root.right, unAddedMap);}

遞歸插入

private static void addRecursively(Node root, Map<Character, Node> map) {if (root == null) {return;}map.put(root.data, root);addRecursively(root.left, map);addRecursively(root.right, map);}

最后的結(jié)果也需要遞歸先序遍歷

private static void preOrder(Node root) {if (root == null) {return;}System.out.print(root.data);preOrder(root.left);preOrder(root.right);}

第一次提交——CE

這次CE就是因為沒把Node類作為內(nèi)部類,不能被OJ識別所以判錯。。。。

第二次提交——WA

這個WA就是因為沒換,具體原因我忘了誒,代碼奉上,可以自己發(fā)掘其“魅力”(毫無魅力的破代碼)
這是錯的哈,正解在下面。。。

import java.util.*;public class Main {static class Node {char data;Node left, right;Node(char data) {this.data = data;this.left = null;this.right = null;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Node node = (Node) o;return data == node.data;}@Overridepublic int hashCode() {return Objects.hash(data);}}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = Integer.parseInt(scanner.nextLine());if (num == 0) {return;}//樹非空,進(jìn)行一系列初始化Map<Character, Node> map = new HashMap<>(num);Map<Character, Node> unAddedMap = new HashMap<>(num);char[] firstChars = scanner.nextLine().toCharArray();//初始化根結(jié)點Node root = new Node(firstChars[0]);map.put(firstChars[0], root);if (firstChars[1] != '*') {root.left = new Node(firstChars[1]);map.put(firstChars[1], root.left);}if (firstChars[2] != '*') {root.right = new Node(firstChars[2]);map.put(firstChars[2], root.right);}//循環(huán)num-1次for (int i = 1; i < num; i++) {char[] chars = scanner.nextLine().toCharArray();//根、左兒子、右兒子的charchar tempRootChar = chars[0], tempLeftChar = chars[1], tempRightChar = chars[2];//臨時的根結(jié)點、左兒子結(jié)點、右兒子結(jié)點Node tempRoot, tempLeft, tempRight;//Map里已有,也就是說已經(jīng)存在臨時父結(jié)點,而且子結(jié)點也有咯if (map.containsKey(tempRootChar)) {tempRoot = map.get(tempRootChar);//子結(jié)點必定不存在于Map,但要看看unAddedif (unAddedMap.containsKey(tempLeftChar)) {tempLeft = unAddedMap.get(tempLeftChar);root.left = tempLeft;addRecursively(tempLeft, map);deleteRecursively(tempLeft, unAddedMap);} else if (tempLeftChar == '*') {tempLeft = null;} else {tempLeft = new Node(tempLeftChar);}if (unAddedMap.containsKey(tempRightChar)) {tempRight = unAddedMap.get(tempRightChar);root.right = tempRight;addRecursively(tempRight, map);deleteRecursively(tempRight, unAddedMap);} else if (tempRightChar == '*') {tempRight = null;} else {tempRight = new Node(tempRightChar);}//插入左右兒子節(jié)點tempRoot.left = tempLeft;tempRoot.right = tempRight;} else if (unAddedMap.containsKey(tempRootChar)) { //這就是說它的父結(jié)點已經(jīng)存在咯,然后還沒插進(jìn)樹里//繼續(xù)放在unAdded里tempRoot = unAddedMap.get(tempRootChar);//子結(jié)點必定不存在//插入左右兒子節(jié)點if (tempLeftChar != '*') {tempLeft = new Node(tempLeftChar);tempRoot.left = tempLeft;unAddedMap.put(tempLeftChar, tempLeft);}if (tempRightChar != '*') {tempRight = new Node(tempRightChar);tempRoot.right = tempRight;unAddedMap.put(tempRightChar, tempRight);}} else { //兩邊都沒有,看看是不是子結(jié)點就是現(xiàn)在的根tempRoot = new Node(tempRootChar);if (tempLeftChar == '*') {tempLeft = null;} else {tempLeft = new Node(tempLeftChar);tempRoot.left = tempLeft;}if (tempRightChar == '*') {tempRight = null;} else {tempRight = new Node(tempRightChar);tempRoot.right = tempRight;}if (root.equals(tempLeft)) { //左兒子是根結(jié)點,換根tempLeft = root;tempRoot.left = tempLeft;root = tempRoot;//查找右兒子if (unAddedMap.containsKey(tempRightChar)) {tempRight = unAddedMap.get(tempRightChar);root.right = tempRight;addRecursively(tempRight, map);deleteRecursively(tempRight, unAddedMap);}} else if (root.equals(tempRight)) { //右兒子是根結(jié)點,換根tempRight = root;tempRoot.right = tempRight;root = tempRoot;//查找左兒子if (unAddedMap.containsKey(tempLeftChar)) {tempLeft = unAddedMap.get(tempLeftChar);root.left = tempLeft;addRecursively(tempLeft, map);deleteRecursively(tempLeft, unAddedMap);}} else { //插入unAdded里if (unAddedMap.containsKey(tempLeftChar)) {tempRoot.left = unAddedMap.get(tempLeftChar);} else if (tempLeftChar != '*') {unAddedMap.put(tempLeftChar, tempLeft);}if (unAddedMap.containsKey(tempRightChar)) {tempRoot.right = unAddedMap.get(tempRightChar);} else if (tempRightChar != '*') {unAddedMap.put(tempRightChar, tempRight);}unAddedMap.put(tempRootChar, tempRoot);}}}scanner.close();preOrder(root);}private static void preOrder(Node root) {if (root == null) {return;}System.out.print(root.data);preOrder(root.left);preOrder(root.right);}private static void deleteRecursively(Node root, Map<Character, Node> unAddedMap) {if (root == null) {return;}unAddedMap.remove(root.data);deleteRecursively(root.left, unAddedMap);deleteRecursively(root.right, unAddedMap);}private static void addRecursively(Node root, Map<Character, Node> map) {if (root == null) {return;}map.put(root.data, root);addRecursively(root.left, map);addRecursively(root.right, map);}}

哦~~我竟截圖為證。。。
好吧,改的是這里,就AC了:

AC代碼(Java語言描述)

import java.util.*;public class Main {static class Node {char data;Node left, right;Node(char data) {this.data = data;this.left = null;this.right = null;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Node node = (Node) o;return data == node.data;}@Overridepublic int hashCode() {return Objects.hash(data);}}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = Integer.parseInt(scanner.nextLine());if (num == 0) {return;}//樹非空,進(jìn)行一系列初始化Map<Character, Node> map = new HashMap<>(num);Map<Character, Node> unAddedMap = new HashMap<>(num);char[] firstChars = scanner.nextLine().toCharArray();//初始化根結(jié)點Node root = new Node(firstChars[0]);map.put(firstChars[0], root);if (firstChars[1] != '*') {root.left = new Node(firstChars[1]);map.put(firstChars[1], root.left);}if (firstChars[2] != '*') {root.right = new Node(firstChars[2]);map.put(firstChars[2], root.right);}//循環(huán)num-1次for (int i = 1; i < num; i++) {char[] chars = scanner.nextLine().toCharArray();//根、左兒子、右兒子的charchar tempRootChar = chars[0], tempLeftChar = chars[1], tempRightChar = chars[2];//臨時的根結(jié)點、左兒子結(jié)點、右兒子結(jié)點Node tempRoot, tempLeft, tempRight;//Map里已有,也就是說已經(jīng)存在臨時父結(jié)點,而且子結(jié)點肯定沒有if (map.containsKey(tempRootChar)) {tempRoot = map.get(tempRootChar);//子結(jié)點必定不存在于Map,但要看看unAddedif (unAddedMap.containsKey(tempLeftChar)) {tempLeft = unAddedMap.get(tempLeftChar);root.left = tempLeft;addRecursively(tempLeft, map);deleteRecursively(tempLeft, unAddedMap);} else if (tempLeftChar == '*') {tempLeft = null;} else {tempLeft = new Node(tempLeftChar);map.put(tempLeftChar, tempLeft);}if (unAddedMap.containsKey(tempRightChar)) {tempRight = unAddedMap.get(tempRightChar);root.right = tempRight;addRecursively(tempRight, map);deleteRecursively(tempRight, unAddedMap);} else if (tempRightChar == '*') {tempRight = null;} else {tempRight = new Node(tempRightChar);map.put(tempRightChar, tempRight);}//插入左右兒子節(jié)點tempRoot.left = tempLeft;tempRoot.right = tempRight;} else if (unAddedMap.containsKey(tempRootChar)) { //這就是說它的父結(jié)點已經(jīng)存在咯,然后還沒插進(jìn)樹里//繼續(xù)放在unAdded里tempRoot = unAddedMap.get(tempRootChar);//子結(jié)點必定不存在//插入左右兒子節(jié)點if (tempLeftChar != '*') {tempLeft = new Node(tempLeftChar);tempRoot.left = tempLeft;unAddedMap.put(tempLeftChar, tempLeft);}if (tempRightChar != '*') {tempRight = new Node(tempRightChar);tempRoot.right = tempRight;unAddedMap.put(tempRightChar, tempRight);}} else { //兩邊都沒有,看看是不是子結(jié)點就是現(xiàn)在的根tempRoot = new Node(tempRootChar);if (tempLeftChar == '*') {tempLeft = null;} else {tempLeft = new Node(tempLeftChar);tempRoot.left = tempLeft;}if (tempRightChar == '*') {tempRight = null;} else {tempRight = new Node(tempRightChar);tempRoot.right = tempRight;}if (root.equals(tempLeft)) { //左兒子是根結(jié)點,換根tempLeft = root;tempRoot.left = tempLeft;root = tempRoot;//查找右兒子if (unAddedMap.containsKey(tempRightChar)) {tempRight = unAddedMap.get(tempRightChar);root.right = tempRight;addRecursively(tempRight, map);deleteRecursively(tempRight, unAddedMap);}} else if (root.equals(tempRight)) { //右兒子是根結(jié)點,換根tempRight = root;tempRoot.right = tempRight;root = tempRoot;//查找左兒子if (unAddedMap.containsKey(tempLeftChar)) {tempLeft = unAddedMap.get(tempLeftChar);root.left = tempLeft;addRecursively(tempLeft, map);deleteRecursively(tempLeft, unAddedMap);}} else { //插入unAdded里if (unAddedMap.containsKey(tempLeftChar)) {tempRoot.left = unAddedMap.get(tempLeftChar);} else if (tempLeftChar != '*') {unAddedMap.put(tempLeftChar, tempLeft);}if (unAddedMap.containsKey(tempRightChar)) {tempRoot.right = unAddedMap.get(tempRightChar);} else if (tempRightChar != '*') {unAddedMap.put(tempRightChar, tempRight);}unAddedMap.put(tempRootChar, tempRoot);}}}scanner.close();preOrder(root);}private static void preOrder(Node root) {if (root == null) {return;}System.out.print(root.data);preOrder(root.left);preOrder(root.right);}private static void deleteRecursively(Node root, Map<Character, Node> unAddedMap) {if (root == null) {return;}unAddedMap.remove(root.data);deleteRecursively(root.left, unAddedMap);deleteRecursively(root.right, unAddedMap);}private static void addRecursively(Node root, Map<Character, Node> map) {if (root == null) {return;}map.put(root.data, root);addRecursively(root.left, map);addRecursively(root.right, map);}}

感想

這代碼真簡(la)潔(ji)。。。
我迷了,不過自己手寫一次滿有收獲的誒,奧利給!!!!
容我休息一下~~~
寫代碼好快(tou)樂(tu)。。。。
您能看完,是賞臉的,菜雞拜謝Orz

傳說七只Orz的自己可以召喚神龍哇!!!

總結(jié)

以上是生活随笔為你收集整理的用任意合法序列建立一棵二叉树(洛谷P1305题题解,Java语言描述)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。