forked from liuyubobobo/Play-with-Data-Structures
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.java
161 lines (127 loc) · 4.75 KB
/
Solution.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import java.util.ArrayList;
import java.util.List;
import javafx.util.Pair;
/// Leetcode 102. Binary Tree Level Order Traversal
/// https://leetcode.com/problems/binary-tree-level-order-traversal/description/
/// 二叉树的层序遍历
///
/// 二叉树的层序遍历是一个典型的可以借助队列解决的问题。
/// 该代码主要用于使用Leetcode上的问题测试我们的LoopQueue。
/// 对于二叉树的层序遍历,这个课程后续会讲到。
/// 届时,同学们也可以再回头看这个代码。
/// 不过到时,大家应该已经学会自己编写二叉树的层序遍历啦:)
class Solution {
/// Definition for a binary tree node.
private class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
private interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
// 在这一版LoopQueue的实现中,我们将不浪费那1个空间:)
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front, tail;
private int size;
public LoopQueue(int capacity){
data = (E[])new Object[capacity]; // 由于不浪费空间,所以data静态数组的大小是capacity
// 而不是capacity + 1
front = 0;
tail = 0;
size = 0;
}
public LoopQueue(){
this(10);
}
public int getCapacity(){
return data.length;
}
@Override
public boolean isEmpty(){
// 注意,我们不再使用front和tail之间的关系来判断队列是否为空,而直接使用size
return size == 0;
}
@Override
public int getSize(){
return size;
}
@Override
public void enqueue(E e){
// 注意,我们不再使用front和tail之间的关系来判断队列是否为满,而直接使用size
if(size == getCapacity())
resize(getCapacity() * 2);
data[tail] = e;
tail = (tail + 1) % data.length;
size ++;
}
@Override
public E dequeue(){
if(isEmpty())
throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size --;
if(size == getCapacity() / 4 && getCapacity() / 2 != 0)
resize(getCapacity() / 2);
return ret;
}
@Override
public E getFront(){
if(isEmpty())
throw new IllegalArgumentException("Queue is empty.");
return data[front];
}
private void resize(int newCapacity){
E[] newData = (E[])new Object[newCapacity];
for(int i = 0 ; i < size ; i ++)
newData[i] = data[(i + front) % data.length];
data = newData;
front = 0;
tail = size;
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append(String.format("Queue: size = %d , capacity = %d\n", size, getCapacity()));
res.append("front [");
// 注意,我们的循环遍历打印队列的逻辑也有相应的更改 :-)
for(int i = 0; i < size; i ++){
res.append(data[(front + i) % data.length]);
if((i + front + 1) % data.length != tail)
res.append(", ");
}
res.append("] tail");
return res.toString();
}
}
public List<List<Integer>> levelOrder(TreeNode root) {
ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
if(root == null)
return res;
// 我们使用LinkedList来做为我们的先入先出的队列
LoopQueue<Pair<TreeNode, Integer>> queue = new LoopQueue<Pair<TreeNode, Integer>>();
queue.enqueue(new Pair<TreeNode, Integer>(root, 0));
while(!queue.isEmpty()){
Pair<TreeNode, Integer> front = queue.dequeue();
TreeNode node = front.getKey();
int level = front.getValue();
if(level == res.size())
res.add(new ArrayList<Integer>());
assert level < res.size();
res.get(level).add(node.val);
if(node.left != null)
queue.enqueue(new Pair<TreeNode, Integer>(node.left, level + 1));
if(node.right != null)
queue.enqueue(new Pair<TreeNode, Integer>(node.right, level + 1));
}
return res;
}
}