單鏈表
題目描述
實現一個單鏈表,鏈表初始爲空,支持三種操作:
(1) 向鏈表頭插入一個數;
(2) 刪除第k個插入的數後面的數;
(3) 在第k個插入的數後插入一個數
現在要對該鏈表進行M次操作,進行完所有操作後,從頭到尾輸出整個鏈表。
注意:題目中第k個插入的數並不是指當前鏈表的第k個數。例如操作過程中一共插入了n個數,則按照插入的時間順序,這n個數依次爲:第1個插入的數,第2個插入的數,…第n個插入的數。
輸入格式
第一行包含整數M,表示操作次數。
接下來M行,每行包含一個操作命令,操作命令可能爲以下幾種:
(1) “H x”,表示向鏈表頭插入一個數x。
(2) “D k”,表示刪除第k個輸入的數後面的數(當k爲0時,表示刪除頭結點)。
(3) “I k x”,表示在第k個輸入的數後面插入一個數x(此操作中k均大於0)。
輸出格式
共一行,將整個鏈表從頭到尾輸出。
數據範圍
1≤M≤100000
所有操作保證合法。
輸入樣例:
10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6
輸出樣例:
6 4 6 5
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 6 ;
int head,e[N],ne[N],idx;
void start(){
head = - 1 , idx = 0 ;
}
//在表頭插入一個元素x
void insert_head(int x){
e[idx] = x , ne[idx] = head , head = idx ++ ;
}
//將X插到下標是K的後面
void insert(int k,int x){
e[idx] = x ,ne[idx] = ne[k] ,ne[k] = idx ++ ;
}
//刪除第k個輸入的數後面的數
void remove(int x){
ne[x] = ne[ne[x]];
}
int main(){
start();
int m;
scanf("%d",&m);
while(m--){
char op;
int x,k;
cin>>op;
if(op == 'H') cin>>x,insert_head(x);
else if(op == 'D'){
cin>>k;
if(!k) head = ne[head];
else remove(k-1);
}
else cin>>k>>x,insert(k-1,x);
}
for(int i = head; i != - 1; i = ne[i]) cout<<e[i]<<" ";
cout<<endl;
return 0;
}
雙鏈表
實現一個雙鏈表,雙鏈表初始爲空,支持5種操作:
(1) 在最左側插入一個數;
(2) 在最右側插入一個數;
(3) 將第k個插入的數刪除;
(4) 在第k個插入的數左側插入一個數;
(5) 在第k個插入的數右側插入一個數
現在要對該鏈表進行M次操作,進行完所有操作後,從左到右輸出整個鏈表。
注意:題目中第k個插入的數並不是指當前鏈表的第k個數。例如操作過程中一共插入了n個數,則按照插入的時間順序,這n個數依次爲:第1個插入的數,第2個插入的數,…第n個插入的數。
輸入格式
第一行包含整數M,表示操作次數。
接下來M行,每行包含一個操作命令,操作命令可能爲以下幾種:
(1) “L x”,表示在鏈表的最左端插入數x。
(2) “R x”,表示在鏈表的最右端插入數x。
(3) “D k”,表示將第k個插入的數刪除。
(4) “IL k x”,表示在第k個插入的數左側插入一個數。
(5) “IR k x”,表示在第k個插入的數右側插入一個數。
輸出格式
共一行,將整個鏈表從左到右輸出。
數據範圍
1≤M≤100000
所有操作保證合法。
輸入樣例:
10
R 7
D 1
L 3
IL 2 10
D 3
IL 2 7
L 8
R 9
IL 4 7
IR 2 2
輸出樣例:
8 7 7 3 2 9
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 6 ;
int head,l[N],r[N],e[N],idx;
void start(){
//0左1右
r[0] = 1 , l[1] = 0 ;
idx = 2;
}
//在節點a的右面插入一個數x
void insert(int a,int x){
e[idx] = x ;
l[idx] = a , r[idx] = r[a] ;
l[r[a]] = idx , r[a] = idx ++ ;
}
//刪除節點a
void remove(int a){
l[r[a]] = l[a] ;
r[l[a]] = r[a] ;
}
int main(){
start();
int m;
scanf("%d",&m);
while(m--){
int k,x;
string oper;
cin>>oper;
if(oper == "L") cin>>x,insert(0,x);
else if(oper == "R") cin>>x,insert(l[1],x);
else if(oper == "D") cin>>k,remove(k+1);
else if(oper == "IL") cin>>k>>x,insert(l[k+1],x);
else if(oper == "IR") cin>>k>>x,insert(k+1,x);
}
for(int i = r[0] ; i != 1; i = r[i]) cout<<e[i]<<" ";
cout<<endl;
return 0;
}
模擬棧
實現一個棧,棧初始爲空,支持四種操作:
(1) “push x” – 向棧頂插入一個數x;
(2) “pop” – 從棧頂彈出一個數;
(3) “empty” – 判斷棧是否爲空;
(4) “query” – 查詢棧頂元素。
現在要對棧進行M個操作,其中的每個操作3和操作4都要輸出相應的結果。
輸入格式
第一行包含整數M,表示操作次數。
接下來M行,每行包含一個操作命令,操作命令爲”push x”,”pop”,”empty”,”query”中的一種。
輸出格式
對於每個”empty”和”query”操作都要輸出一個查詢結果,每個結果佔一行。
其中,”empty”操作的查詢結果爲“YES”或“NO”,”query”操作的查詢結果爲一個整數,表示棧頂元素的值。
數據範圍
1≤M≤100000,
1≤x≤109
所有操作保證合法。
輸入樣例:
10
push 5
query
push 6
pop
query
pop
empty
push 4
query
empty
輸出樣例:
5
5
YES
4
NO
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+6;
int m,st[N],tt;
int main(){
cin>>m;
while(m--){
string op;
int x;
cin>>op;
if(op=="push"){
cin>>x;
st[++tt]=x;
}
else if(op=="pop") tt--;
else if(op=="empty"){
if(tt) puts("NO");
else puts("YES");
}
else cout<<st[tt]<<endl;
}
return 0;
}
模擬隊列
實現一個隊列,隊列初始爲空,支持四種操作:
(1) “push x” – 向隊尾插入一個數x;
(2) “pop” – 從隊頭彈出一個數;
(3) “empty” – 判斷隊列是否爲空;
(4) “query” – 查詢隊頭元素。
現在要對隊列進行M個操作,其中的每個操作3和操作4都要輸出相應的結果。
輸入格式
第一行包含整數M,表示操作次數。
接下來M行,每行包含一個操作命令,操作命令爲”push x”,”pop”,”empty”,”query”中的一種。
輸出格式
對於每個”empty”和”query”操作都要輸出一個查詢結果,每個結果佔一行。
其中,”empty”操作的查詢結果爲“YES”或“NO”,”query”操作的查詢結果爲一個整數,表示隊頭元素的值。
數據範圍
1≤M≤100000,
1≤x≤109,
所有操作保證合法。
輸入樣例:
10
push 6
empty
query
pop
empty
push 3
push 4
pop
query
push 6
輸出樣例:
NO
6
YES
4
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int m,q[N],hh,tt=-1;
int main(){
cin>>m;
while(m--){
string op;
int x;
cin>>op;
if(op=="push"){
cin>>x;
q[++tt]=x;
}
else if(op=="pop") hh++;
else if(op=="empty"){
if(hh<=tt) puts("NO");
else puts("YES");
}
else cout<<q[hh]<<endl;
}
return 0;
}
單調棧
給定一個長度爲N的整數數列,輸出每個數左邊第一個比它小的數,如果不存在則輸出-1。
輸入格式
第一行包含整數N,表示數列長度。
第二行包含N個整數,表示整數數列。
輸出格式
共一行,包含N個整數,其中第i個數表示第i個數的左邊第一個比它小的數,如果不存在則輸出-1。
數據範圍
1≤N≤105
1≤數列中元素≤109
輸入樣例:
5
3 4 2 7 5
輸出樣例:
-1 3 -1 2 2
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
int st[N],tt;
int main(){
int n;
cin>>n;
while(n--){
int x;
cin>>x;
while(tt&&st[tt]>=x) tt--;
if(!tt) cout<<"-1 ";
else printf("%d ",st[tt]);
st[++tt]=x;
}
return 0;
}
滑動窗口
給定一個大小爲n≤106的數組。
有一個大小爲k的滑動窗口,它從數組的最左邊移動到最右邊。
您只能在窗口中看到k個數字。
每次滑動窗口向右移動一個位置。
以下是一個例子:
該數組爲[1 3 -1 -3 5 3 6 7],k爲3。
窗口位置 最小值 最大值
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3] 5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7
您的任務是確定滑動窗口位於每個位置時,窗口中的最大值和最小值。
輸入格式
輸入包含兩行。
第一行包含兩個整數n和k,分別代表數組長度和滑動窗口的長度。
第二行有n個整數,代表數組的具體數值。
同行數據之間用空格隔開。
輸出格式
輸出包含兩個。
第一行輸出,從左至右,每個位置滑動窗口中的最小值。
第二行輸出,從左至右,每個位置滑動窗口中的最大值。
輸入樣例:
8 3
1 3 -1 -3 5 3 6 7
輸出樣例:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+7;
int a[N],q[N];
int main(){
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
int hh=0,tt=-1;
for(int i=0;i<n;i++){
if(hh<=tt&&i-k+1>q[hh]) hh++;
while(hh<=tt&&a[q[tt]]>=a[i]) tt--;
q[++tt]=i;
if(i>=k-1) printf("%d ",a[q[hh]]);
}
cout<<endl;
hh=0,tt=-1;
for(int i=0;i<n;i++){
if(hh<=tt&&i-k+1>q[hh]) hh++;
while(hh<=tt&&a[q[tt]]<=a[i]) tt--;
q[++tt]=i;
if(i>=k-1) printf("%d ",a[q[hh]]);
}
cout<<endl;
return 0;
}
未完待續