Briefly Speaking : how to store data in a computer
Like a Library
Your book is data
And how to sort and store these books
Target : find a book a quick as possible
Where to put this book?
Delete this book
Maybe need to check
Solving a Problem
(multi) Data Structure + (multi) Algorithm
push/insert : put in an element
pop/delete : take out an element
query : search, if-exist, quantitiy, max, min
Properties
| Outcome |
|---|
| Stack |
|---|
| Operation |
|---|
<- top
| Outcome |
|---|
| Stack |
|---|
| Operation |
|---|
| push 1 |
<- top
| Outcome |
|---|
| Stack |
|---|
| 1 |
| Operation |
|---|
| push 1 |
<- top
| Outcome |
|---|
| Stack |
|---|
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
<- top
| Outcome |
|---|
| Stack |
|---|
| 19 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
<- top
| Outcome |
|---|
| Stack |
|---|
| 19 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
<- top
| Outcome |
|---|
| Stack |
|---|
| 35 |
| 19 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
<- top
| Outcome |
|---|
| Stack |
|---|
| 35 |
| 19 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
<- top
| Outcome |
|---|
| 35 |
| Stack |
|---|
| 19 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
<- top
| Outcome |
|---|
| 35 |
| Stack |
|---|
| 19 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
<- top
| Outcome |
|---|
| 35 |
| 19 |
| Stack |
|---|
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
<- top
| Outcome |
|---|
| 35 |
| 19 |
| Stack |
|---|
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
| push 7 |
<- top
| Outcome |
|---|
| 35 |
| 19 |
| Stack |
|---|
| 7 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
| push 7 |
<- top
| Outcome |
|---|
| 35 |
| 19 |
| Stack |
|---|
| 7 |
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
| push 7 |
| pop |
<- top
| Outcome |
|---|
| 35 |
| 19 |
| 7 |
| Stack |
|---|
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
| push 7 |
| pop |
<- top
| Outcome |
|---|
| 35 |
| 19 |
| 7 |
| Stack |
|---|
| 1 |
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
| push 7 |
| pop |
| pop |
<- top
| Outcome |
|---|
| 35 |
| 19 |
| 7 |
| 1 |
| Stack |
|---|
| Operation |
|---|
| push 1 |
| push 19 |
| push 35 |
| pop |
| pop |
| push 7 |
| pop |
| pop |
<- top
| 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
push 4
top = -1
| 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| 4 |
top = 0
push 7
| 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| 4 | 7 |
top = 1
pop, outcome = 7
| 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| 4 |
top = 0
push 17, push 39
| 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| 4 | 17 | 39 |
top = 2
push 25, pop, pop, push 14 pop
What are the outcomes , top, and remaining value in array ?
#include <stack>
std::stack<int> steak;
steak.push(10);
steak.push(18);
std::cout << steak.top() << '\n';
// return the top value of stack. No pop out.
steak.pop();
// only pop out the top one of stack, no return;
std::cout << steak.top() << '\n';
Please share your screen
Homework
Use stack
(佇列)
Same
| Outcome |
|---|
| Queue |
|---|
| Operation |
|---|
<- front = rear
| Outcome |
|---|
| Queue |
|---|
| Operation |
|---|
| push 'a' |
<- front = rear
| Outcome |
|---|
| Queue |
|---|
| a |
| Operation |
|---|
| push 'a' |
<- front
<- rear
| Outcome |
|---|
| Queue |
|---|
| a |
| Operation |
|---|
| push 'a' |
| push 't' |
<- front
<- rear
| Outcome |
|---|
| Queue |
|---|
| t |
| a |
| Operation |
|---|
| push 'a' |
| push 't' |
<- front
<- rear
| Outcome |
|---|
| Queue |
|---|
| t |
| a |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
<- front
<- rear
| Outcome |
|---|
| a |
| Queue |
|---|
| t |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
<- front
<- rear
| Outcome |
|---|
| a |
| Queue |
|---|
| t |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
<- front
<- rear
| Outcome |
|---|
| a |
| Queue |
|---|
| e |
| t |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
<- front
<- rear
| Outcome |
|---|
| a |
| Queue |
|---|
| e |
| t |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
<- front
<- rear
| Outcome |
|---|
| a |
| Queue |
|---|
| k |
| e |
| t |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
<- front
<- rear
| Outcome |
|---|
| a |
| Queue |
|---|
| k |
| e |
| t |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
<- front
<- rear
| Outcome |
|---|
| a |
| t |
| Queue |
|---|
| k |
| e |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
<- front
<- rear
| Outcome |
|---|
| a |
| t |
| Queue |
|---|
| k |
| e |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
| pop |
<- front
<- rear
| Outcome |
|---|
| a |
| t |
| e |
| Queue |
|---|
| k |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
| pop |
<- front
<- rear
| Outcome |
|---|
| a |
| t |
| e |
| Queue |
|---|
| k |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
| pop |
| pop |
<- front
<- rear
| Outcome |
|---|
| a |
| t |
| e |
| k |
| Queue |
|---|
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
| pop |
| pop |
<- front =rear
Now Stack is empty !!
| Outcome |
|---|
| a |
| t |
| e |
| k |
| Queue |
|---|
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
| pop |
| pop |
| push 'm' |
<- front =rear
Now Stack is empty !!
| Outcome |
|---|
| a |
| t |
| e |
| k |
| Queue |
|---|
| m |
| Operation |
|---|
| push 'a' |
| push 't' |
| pop |
| push 'e' |
| push 'k' |
| pop |
| pop |
| pop |
| push 'm' |
<- front
Now Stack is empty !!
<- rear
| 0 | 1 | ... | 21473646 | 21473657 |
|---|---|---|---|---|
| k |
^------------------------unused-----------^
front
rear
The problem : if an element is popped out,
that position can't be used anymore.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| k | a | e |
front
rear
when rear is at the end, move(shift) all element to the begin.
pushing an 'r'
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| k | a | e | r |
front
rear
When rear is at the end, move(shift) all element to the begin.
shift then push an 'r'
We just push then element as usual
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| r | k | a | e |
front
rear
pushing an 'r'
What should be aware of ?
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| r | k | l | k | a | e |
front
rear
Sacrifice a place and note that when
rear == front -> empty
rear == front -1 -> full
Actually, in some problem, the size of input is not so big.
We can just allocate an array that large enough.
Later we will mention
push |
pop |
|
|---|---|---|
stack |
O(1) |
O(1) |
queue |
O(1) |
O(1) |
#include <queue>
std::queue<int> que;
que.push(1);
std::cout << que.front() << '\n';
// return the value of first element
// (the next one to be pop),
// not performing pop
que.push(2);
std::cout << que.front() << '\n';
que.pop();
// pop out the firsst element, no return
std::cout << que.front() << '\n';What are the outputs ?
Homework UVa-540
(鏈結串列)
There are N trains, each one has M carriages
Now you have some work to do
connect a-th train to b-th train
and the station master ask you how is the final train like
We just simply connect the train
| 0 | 1 | 2 | 3 | 4 | ... | |
|---|---|---|---|---|---|---|
| train 1 | 1 | 3 | ||||
| train 2 | 5 | 7 | ||||
| train 3 | 9 | 11 |
How long should an array be ?
N trains, M carriages
Largest possible train is N*M
So your array should be N*M long...
| 0 | 1 | 2 | 3 | 4 | ... | |
|---|---|---|---|---|---|---|
| train 1 | 1 | 3 | ||||
| train 2 | 5 | 7 | 9 | 11 | ||
| train 3 |
for (int i = 0; i < len_b; i++){
train_a[len_a + i] = train_b[i];
}
len_a += len_b;Node : (data + pointer) (like carriage)
link lots of nodes together
use a pointer "head" point to the first node
the last node point to null
struct Node{
int _data;
Node * _next;
}
int main(){
Node* node = new Node();
}void insert(Node *A, Node* B){
A->_next = B;
}void delete(Node *A){
Node * tode = A->next;
A->next = A->next->next;
delete tode; // free memory
}Is there some problem about the code ?
void delete(Node *A){
Node * tode = A->next;
if(A->next != nullptr){
A->next = A->next->next;
delete tode; // free memory
}else{
A->next = nullptr;
}
}class Stack{
private:
struct Node{
Node *_next;
int _data;
}
Node * head
public:
void push(int val){
Node * newNode = new Node(val);
newNode->next = head;
head = newNode;
}
void pop(int val){
Node * tode = head;
head = head->next;
delete head;
}
};class Stack{
private:
struct Node{
Node *_next;
int _data;
}
Node * head;
Node * end;
public:
void push(int val){
Node * newNode = new Node(val);
end->next = newNode;
end = newNode;
}
void pop(int val){
Node * tode = head;
head = head->next;
delete head;
}
};| random access | push front |
push back |
pop front |
pop back |
|
|---|---|---|---|---|---|
| Array | yes | O(n) | O(1) | O(n) | O(1) |
| Linked List | No | O(1) | O(1) | O(1) | O(1) |
give you a string of parentheses, determine if it is legal
"{([])([]{{}[]})}" => legal
"({([][]))} => illegal
Count how many left parenthesis and right parenthesis ?
How about this ?
{ [ ( ] ) } ?
Use stack !!
push in when encounter left one
pop out when match right
The maximum Rectangle in a Bar Graph
The maximum Rectangle in a Bar Graph
Try to implement Stack & Queue by yourself
And get AC of previous problems use your own stack & queue
Remember to send me the AC screen shot !
We stimulate the stack directly
And try to produce the order it wants
So
1. if the top is equal to the current wanting order, pop out
2. if the top is not equal, we can't pop.
So we put another new train into stack
up_coming = 1
push up_coming into stack
up_coming = up_coming + 1
want = 0
while up_coming <= N or stack isn't empty
if(order[want] equal to top of stack)
pop out stack
else
push up_coming into stack
up_coming = up_coming+1
If the order is valid
then all element in stack will eventually popped out due to matching.
If the order is invalid
eventually there must some place the stack start to unmatch
and never match again.
So in all element pushed into stack and still not matching
It must be invalid
up_coming = 1
push up_coming into stack
up_coming = up_coming + 1
want = 0
while up_coming <= N or stack isn't empty
if(order[want] equal to top of stack)
pop out stack
else
push up_coming into stack
up_coming = up_coming+1
if(up_coming == N+1 and the top of stack != order[want])
failed
break
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| a | x |
|---|
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| a | x | y |
|---|
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| a | b | x | y |
|---|
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| b | x | y |
|---|
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| b | x | y | r |
|---|
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| b | c | x | y | r |
|---|
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
We think as a group queue
| b | c |
|---|
| x | y |
|---|
| r |
|---|
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
We think as a group queue
| c |
|---|
| x | y |
|---|
| r |
|---|
when popping... pop the element from the top queue of group queue
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
We think as a group queue
| x | y |
|---|
| r |
|---|
when popping... pop the element from the top queue of group queue
when popping... pop the top queue of group queue
if the top queue is empty
Here is the assumption
If two person who both in the same group is in the queue, the must be contiguous.
| groups |
|---|
| a, b, c |
| x, y, z |
| r, v |
We think as a group queue
| x | y |
|---|
| r | v |
|---|
when pushing... check if the group it belongs is in group queue
if yes, push the corresponding queue
if no, push a new group into group queue and push element into that new queue
| a |
|---|
if left
put into stack
if right
check if it's match with top
if not
error
if matched
pop
Given an array of integer
ask about the first number on the right of number that greater than this number.
ex. 3 2 1 6 3 7 5 4 2 1 8 9
6 6 6 7 7 8 8 8 8 8 9 -1
Formal input description
the first line is an integer N, N <= 10^7
2nd line contains N integers
3rd line is an integer Q, Q<=10^7
and following Q lines
each line have one integer x, 0<=x<=N-1, represent the index
for each x, output the first element greater than x-th element on the right of x-th element
input:
8
3 2 5 7 4 3 9 1
5
3
2
5
1
4
output:
7
5
9
5
9
int seq[10006];
int ans[10006];
int main(){
cin >> N;
for(int i = 0; i < N; i++){
cin >> seq[i];
}
int Q;
cin >> Q;
int index;
for(int i = 0; i < Q; i++){
cin >> index;
for(int j = index; j < N; j++){
if(seq[j] > seq[index-1]){
cout << seq[j] << endl;
}
if(j == N-1){
cout << -1 << endl;
}
}
}
}What is the time complexity ??
int seq[10006];
int ans[10006];
int main(){
cin >> N;
for(int i = 0; i < N; i++){
cin >> seq[i];
}
for(int i = 0; i < N; i++){
for(int j = i + 1; j < N; j++){
if(seq[j] > seq[i]){
ans[j] = seq[i];
break;
}
if(j == N-1)
ans[j] = -1;
}
}
int Q;
cin >> Q;
int index;
for(int i = 0; i < Q; i++){
cin >> index;
cout << ans[index-1] << endl;
}
}What is the time complexity ??
For i-th element
any element after it(j > i) but small than i-th element (seq[j] < seq[i])
can't be the answer of any element in front of i-th element
So we can... skip them!
And only record those who is possible be the anwer.
int seq[10006];
int ans[10006];
int main(){
cin >> N;
stack<int> S;
for(int i = 0; i < N; i++){
cin >> seq[i];
}
for(int i = N-1; i < N; i++){
while(!S.empty() && S.top() <= seq[i]){
S.pop();
}
if(S.empty())
ans[i] = -1;
else
ans[i] = S.top();
S.push(seq[i]);
}
int Q;
cin >> Q;
int index;
for(int i = 0; i < Q; i++){
cin >> index;
cout << ans[index-1] << endl;
}
}What is the time complexity ?? How many times does stack pop() operate ?
int seq[10006];
int ans[10006];
int main(){
cin >> N;
stack<int> S;
for(int i = 0; i < N; i++){
cin >> seq[i];
}
for(int i = N-1; i < N; i++){
while(!S.empty() && S.top() <= seq[i]){
S.pop();
}
if(S.empty())
ans[i] = -1;
else
ans[i] = S.top();
S.push(seq[i]);
}
int Q;
cin >> Q;
int index;
for(int i = 0; i < Q; i++){
cin >> index;
cout << ans[index-1] << endl;
}
}Every element only enter stack and pop out stack once
int seq[10006];
int ans[10006];
int main(){
cin >> N;
stack<int> S;
for(int i = 0; i < N; i++){
cin >> seq[i];
}
for(int i = N-1; i < N; i++){
while(!S.empty() && S.top() <= seq[i]){
S.pop();
}
if(S.empty())
ans[i] = -1;
else
ans[i] = S.top();
S.push(seq[i]);
}
int Q;
cin >> Q;
int index;
for(int i = 0; i < Q; i++){
cin >> index;
cout << ans[index-1] << endl;
}
}We can say that it is still O(n)