Skip to content

Commit 96a6d20

Browse files
committed
feat: 二叉树最大宽度
1 parent 562cc0c commit 96a6d20

File tree

1 file changed

+96
-126
lines changed

1 file changed

+96
-126
lines changed

07-二叉树基本算法.md

Lines changed: 96 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -326,146 +326,116 @@ func main() {
326326

327327
> 找到二叉树的最大宽度
328328
329-
```Java
330-
package class07;
331-
332-
import java.util.HashMap;
333-
import java.util.LinkedList;
334-
import java.util.Queue;
329+
```Go
330+
package main
335331

336-
public class Code06_TreeMaxWidth {
332+
import "math"
337333

338-
public static class Node {
339-
public int value;
340-
public Node left;
341-
public Node right;
334+
type Node struct {
335+
// 二叉树节点上的值
336+
Val int
337+
// 左孩子
338+
Left *Node
339+
// 右孩子
340+
Right *Node
341+
}
342342

343-
public Node(int data) {
344-
this.value = data;
345-
}
343+
// MaxWidthUseMap 给定二叉树头节点,找到该二叉树的最大宽度,借助map结构实现
344+
func (head *Node) MaxWidthUseMap() int {
345+
if head == nil {
346+
return 0
346347
}
348+
hd := head
349+
queue := make([]*Node, 0)
350+
queue = append(queue, hd)
347351

348-
// 方法1使用map
349-
public static int maxWidthUseMap(Node head) {
350-
if (head == null) {
351-
return 0;
352-
}
353-
Queue<Node> queue = new LinkedList<>();
354-
queue.add(head);
355-
// key(节点) 在 哪一层,value
356-
HashMap<Node, Integer> levelMap = new HashMap<>();
357-
// head在第一层
358-
levelMap.put(head, 1);
359-
// 当前你正在统计哪一层的宽度
360-
int curLevel = 1;
361-
// 当前层curLevel层,宽度目前是多少
362-
int curLevelNodes = 0;
363-
// 用来保存所有层的最大值,也就是最大宽度
364-
int max = 0;
365-
while (!queue.isEmpty()) {
366-
Node cur = queue.poll();
367-
int curNodeLevel = levelMap.get(cur);
368-
// 当前节点的左孩子不为空,队列加入左孩子,层数在之前层上加1
369-
if (cur.left != null) {
370-
levelMap.put(cur.left, curNodeLevel + 1);
371-
queue.add(cur.left);
372-
}
373-
// 当前节点的右孩子不为空,队列加入右孩子,层数也变为当前节点的层数加1
374-
if (cur.right != null) {
375-
levelMap.put(cur.right, curNodeLevel + 1);
376-
queue.add(cur.right);
377-
}
378-
// 当前层等于正在统计的层数,不结算
379-
if (curNodeLevel == curLevel) {
380-
curLevelNodes++;
381-
} else {
382-
// 新的一层,需要结算
383-
// 得到目前为止的最大宽度
384-
max = Math.max(max, curLevelNodes);
385-
curLevel++;
386-
// 结算后,当前层节点数设置为1
387-
curLevelNodes = 1;
388-
}
352+
// map的Key:节点 map的value:节点属于哪一层
353+
levelMap := make(map[*Node]int, 0)
354+
// 头节点head属于第一层
355+
levelMap[hd] = 1
356+
// 当前正在统计那一层的宽度
357+
curLevel := 1
358+
// 当前curLevel层,宽度目前是多少
359+
curLevelNodes := 0
360+
// 用来保存所有层的最大宽度的值
361+
max := 0
362+
for len(queue) != 0 {
363+
cur := queue[0]
364+
queue = queue[1:]
365+
curNodeLevel := levelMap[cur]
366+
// 当前节点的左孩子不为空,队列加入左孩子,层数在之前层上加1
367+
if cur.Left != nil {
368+
levelMap[cur.Left] = curNodeLevel + 1
369+
queue = append(queue, cur.Left)
389370
}
390-
// 由于最后一层,没有新的一层去结算,所以这里单独结算最后一层
391-
max = Math.max(max, curLevelNodes);
392-
return max;
393-
}
394-
395-
// 方法2不使用map
396-
public static int maxWidthNoMap(Node head) {
397-
if (head == null) {
398-
return 0;
371+
// 当前节点的右孩子不为空,队列加入右孩子,层数也变为当前节点的层数加1
372+
if cur.Right != nil {
373+
levelMap[cur.Right] = curNodeLevel + 1
374+
queue = append(queue, cur.Right)
399375
}
400-
Queue<Node> queue = new LinkedList<>();
401-
queue.add(head);
402-
// 当前层,最右节点是谁,初始head的就是本身
403-
Node curEnd = head;
404-
// 如果有下一层,下一层最右节点是谁
405-
Node nextEnd = null;
406-
// 全局最大宽度
407-
int max = 0;
408-
// 当前层的节点数
409-
int curLevelNodes = 0;
410-
while (!queue.isEmpty()) {
411-
Node cur = queue.poll();
412-
// 左边不等于空,加入左
413-
if (cur.left != null) {
414-
queue.add(cur.left);
415-
// 孩子的最右节点暂时为左节点
416-
nextEnd = cur.left;
417-
}
418-
// 右边不等于空,加入右
419-
if (cur.right != null) {
420-
queue.add(cur.right);
421-
// 如果有右节点,孩子层的最右要更新为右节点
422-
nextEnd = cur.right;
423-
}
424-
// 由于最开始弹出当前节点,那么该层的节点数加一
425-
curLevelNodes++;
426-
// 当前节点是当前层最右的节点,进行结算
427-
if (cur == curEnd) {
428-
// 当前层的节点和max进行比较,计算当前最大的max
429-
max = Math.max(max, curLevelNodes);
430-
// 即将进入下一层,重置下一层节点为0个节点
431-
curLevelNodes = 0;
432-
// 当前层的最右,直接更新为找出来的下一层最右
433-
curEnd = nextEnd;
434-
}
376+
// 当前层等于正在统计的层数,不结算
377+
if curNodeLevel == curLevel {
378+
curLevelNodes ++
379+
} else {
380+
// 新的一层,需要结算
381+
// 得到目前为止的最大宽度
382+
max = int(math.Max(float64(max), float64(curLevelNodes)))
383+
curLevel++
384+
// 结算后,当前层节点数设置为1
385+
curLevelNodes = 1
435386
}
436-
return max;
437387
}
388+
// 由于最后一层,没有新的一层去结算,所以这里单独结算最后一层
389+
max = int(math.Max(float64(max), float64(curLevelNodes)))
390+
return max
391+
}
438392

439-
// for test
440-
public static Node generateRandomBST(int maxLevel, int maxValue) {
441-
return generate(1, maxLevel, maxValue);
393+
// MaxWidthNoMap 给定二叉树头节点,找到该二叉树的最大宽度,不借助map实现
394+
func (head *Node) MaxWidthNoMap() int {
395+
if head == nil {
396+
return 0
442397
}
443398

444-
// for test
445-
public static Node generate(int level, int maxLevel, int maxValue) {
446-
if (level > maxLevel || Math.random() < 0.5) {
447-
return null;
448-
}
449-
Node head = new Node((int) (Math.random() * maxValue));
450-
head.left = generate(level + 1, maxLevel, maxValue);
451-
head.right = generate(level + 1, maxLevel, maxValue);
452-
return head;
453-
}
399+
hd := head
400+
queue := make([]*Node, 0)
401+
queue = append(queue, hd)
454402

455-
public static void main(String[] args) {
456-
int maxLevel = 10;
457-
int maxValue = 100;
458-
int testTimes = 1000000;
459-
for (int i = 0; i < testTimes; i++) {
460-
Node head = generateRandomBST(maxLevel, maxValue);
461-
if (maxWidthUseMap(head) != maxWidthNoMap(head)) {
462-
System.out.println("Oops!");
463-
}
403+
// 当前层,最右节点是谁,初始head的就是本身
404+
curEnd := head
405+
// 如果有下一层,下一层最右节点是谁
406+
var nextEnd *Node = nil
407+
// 全局最大宽度
408+
max := 0
409+
// 当前层的节点数
410+
curLevelNodes := 0
411+
for len(queue) != 0 {
412+
cur := queue[0]
413+
queue = queue[1:]
414+
// 左边不等于空,加入左
415+
if cur.Left != nil {
416+
queue = append(queue, cur.Left)
417+
// 孩子的最右节点暂时为左节点
418+
nextEnd = cur.Left
464419
}
465-
System.out.println("finish!");
466-
467-
}
468-
420+
// 右边不等于空,加入右
421+
if cur.Right != nil {
422+
queue = append(queue, cur.Right)
423+
// 如果有右节点,孩子层的最右要更新为右节点
424+
nextEnd = cur.Right
425+
}
426+
// 由于最开始弹出当前节点,那么该层的节点数加一
427+
curLevelNodes++
428+
// 当前节点是当前层最右的节点,进行结算
429+
if cur == curEnd {
430+
// 当前层的节点和max进行比较,计算当前最大的max
431+
max = int(math.Max(float64(max), float64(curLevelNodes)))
432+
// 即将进入下一层,重置下一层节点为0个节点
433+
curLevelNodes = 0
434+
// 当前层的最右,直接更新为找出来的下一层最右
435+
curEnd = nextEnd
436+
}
437+
}
438+
return max
469439
}
470440
```
471441

0 commit comments

Comments
 (0)