-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathPeeking Iterator.java
executable file
·188 lines (159 loc) · 5.83 KB
/
Peeking Iterator.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
M
1528087487
tags: Design
#### Use concept pre cache
- 找一个cache来存next()的值, 也就是: next value的值提前存在cache里面
- 因此peek()的时候, 就可以直接return cache, 而不用做 itt.next()
- 然后每次真的next()的时候, 里取下一个itt.next()维护这个cache
#### Previous notes
- 再一次理解错题意. peek() 就是头顶,但是不一定是最大值啊。
- 总是把PEEK想成了最大值,然后用2 STACK做了最大值的cache,练的一手好双stack,可惜错了。
```
/*
Given an Iterator class interface with methods: next() and hasNext(),
design and implement a PeekingIterator that support the peek() operation --
it essentially peek() at the element that will be returned by the next call to next().
Here is an example. Assume that the iterator is initialized to the beginning of the list: [1, 2, 3].
Call next() gets you 1, the first element in the list.
Now you call peek() and it returns 2, the next element. Calling next() after that still return 2.
You call next() the final time and it returns 3, the last element. Calling hasNext() after that should return false.
Hint:
Think of "looking ahead". You want to cache the next element.
Is one variable sufficient? Why or why not?
Test your design with call order of peek() before next() vs next() before peek().
For a clean implementation, check out Google's guava library source code. (https://github.com/google/guava/blob/703ef758b8621cfbab16814f01ddcc5324bdea33/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java#L1125)
Follow up: How would you extend your design to be generic and work with all types, not just integer?
It looks like the guava library uses 'E' for generic element
Tags: Design
Similar Problems: (M) Binary Search Tree Iterator, (M) Flatten 2D Vector, (M) Zigzag Iterator
*/
/*
Second attempt.
Thoughts: Of coruse can't store in a queue, that will be brutle and meaning less.
Instead, use a iterator variable, cache, to hold next().
When called next(), move forward; otherwise, return the cache.
Make sure also return the cached peek, and update cache with next() value.
*/
// Java Iterator interface reference:
// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
class PeekingIterator implements Iterator<Integer> {
private int cache;
private Iterator<Integer> itt;
private boolean notEnd;
public PeekingIterator(Iterator<Integer> iterator) {
// initialize any member here.
itt = iterator;
cache = itt.next();
notEnd = iterator.hasNext();
}
// Returns the next element in the iteration without advancing the iterator.
public Integer peek() {
return cache;
}
// hasNext() and next() should behave the same as in the Iterator interface.
// Override them if needed.
@Override
public Integer next() {
int curr = cache;
notEnd = itt.hasNext();
if (itt.hasNext()) {
cache = itt.next();
}
return curr;
}
@Override
public boolean hasNext() {
return notEnd;
}
}
// Generic and work with all types
// Java Iterator interface reference:
// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
class PeekingIterator<T> implements Iterator<T> {
private T cache;
private Iterator<T> itt;
private boolean notEnd;
public PeekingIterator(Iterator<T> iterator) {
// initialize any member here.
itt = iterator;
cache = itt.next();
notEnd = iterator.hasNext();
}
// Returns the next element in the iteration without advancing the iterator.
public T peek() {
return cache;
}
// hasNext() and next() should behave the same as in the Iterator interface.
// Override them if needed.
@Override
public T next() {
T curr = cache;
notEnd = itt.hasNext();
if (itt.hasNext()) {
cache = itt.next();
}
return curr;
}
@Override
public boolean hasNext() {
return notEnd;
}
}
/*
Attempt1, failed. Reason: I thought we are looking for the real max-peek element! However, this problem only asks for peek() element, which is not necessarily the maximun element. This mistake is bloody.
Thoughts:
To find peek, have to run through the iterator at least once. O(n).
Store everything in 2 stacks:
We want to process the end of the iterator first, put everything into stack.
Therefore the top of the stack is the next() element of iterator.
Also, use second stack to hold max value for each element stage.
Each stack1 element has a max coresponding element in stack2. For example, [5,9,1,3,6]
s1: 6,3,1,9,5 [5 gets out first]
s2: 6,6,6,9,9 [end 9 gets out first]
*/
// Java Iterator interface reference:
// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
class PeekingIterator implements Iterator<Integer> {
private Stack<Integer> s1;
private Stack<Integer> s2;
private int size;
public PeekingIterator(Iterator<Integer> iterator) {
// initialize any member here.
s1 = new Stack<Integer>();
s2 = new Stack<Integer>();
Stack<Integer> temp = new Stack<Integer>();
size = 0;
int max = Integer.MIN_VALUE;
while(iterator.hasNext()) {
temp.push(iterator.next());
size++;
}
while(!temp.empty()) {
s1.push(temp.peek());
max = Math.max(max, temp.peek());
s2.push(max);
temp.pop();
}
}
// Returns the next element in the iteration without advancing the iterator.
public Integer peek() {
if (s1.size() > size) {
s1.pop();
return s2.pop();
} else {
return s2.peek();
}
}
// hasNext() and next() should behave the same as in the Iterator interface.
// Override them if needed.
@Override
public Integer next() {
size--;
return s1.pop();
}
@Override
public boolean hasNext() {
return !s1.empty();
}
}
```