单链表
实现一个单链表,链表初始为空,支持三种操作:
- 向链表头插入一个数;
- 删除第 k 个插入的数后面的数;
- 在第 k 个插入的数后插入一个数。
现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。
注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 11 个插入的数,第 22 个插入的数,…第 n 个插入的数。
输入格式
第一行包含整数 M,表示操作次数。
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:
H x
,表示向链表头插入一个数 x。
D k
,表示删除第 k 个插入的数后面的数(当 k为 0 时,表示删除头结点)。
I k x
,表示在第 k 个插入的数后面插入一个数 x(此操作中 k 均大于 0)。
输出格式
共一行,将整个链表从头到尾输出。
数据范围
1≤M≤100000
所有操作保证合法。
输入样例:
1 2 3 4 5 6 7 8 9 10 11
| 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
|
输出样例:
个人代码
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
| #include<bits/stdc++.h> using namespace std; struct node{ int val; node *next; node():val(0),next(nullptr){} node(int val):val(val),next(nullptr){} node(int val,node *next):val(val),next(next){} }; vector<node*> record; node *head = nullptr; void H(int x) { node* temp = new node(x,head); record.push_back(temp); head = temp; } void I(int x,int y) { node* temp = new node(y,record[x]->next); record.push_back(temp); record[x]->next = temp; } void D(int x) { if (x == 0 && head != nullptr) { head = head->next ; return; } node *temp = record[x]; if (temp->next != nullptr) temp->next = temp->next->next; } void say() { node * temp = head; while(temp != nullptr){ printf("%d ",temp->val); temp = temp->next; } cout<<endl; } int main() { int n;cin>>n; record.push_back(nullptr); while(n--){ char op;cin>>op; if (op == 'H') { int val;cin>>val; H(val); } else if (op == 'I') { int x,y;cin>>x>>y; I(x,y); } else { int x;cin>>x; D(x); } } say(); } /*
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
*/
|
总结点
- 我没有好好的看题题目中的删除我没有确切的定义就开始写代码,导致我错了很多次很难预想没有测例的化我是否能做对这道题
- 时间复杂度的分析考虑到本体的数据量在1e5的大小如果n*n的话会超时考虑用空间换时间
板子
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
| #include <iostream>
using namespace std;
const int N = 100010;
int head, e[N], ne[N], idx;
void init() { head = -1; idx = 0; }
void add_to_head(int x) { e[idx] = x, ne[idx] = head, head = idx ++ ; }
void add(int k, int x) { e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++ ; }
void remove(int k) { ne[k] = ne[ne[k]]; }
int main() { int m; cin >> m;
init();
while (m -- ) { int k, x; char op;
cin >> op; if (op == 'H') { cin >> x; add_to_head(x); } else if (op == 'D') { cin >> k; if (!k) head = ne[head]; else remove(k - 1); } else { cin >> k >> x; add(k - 1, x); } }
for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' '; cout << endl; return 0; }
|
双链表
实现一个双链表,双链表初始为空,支持 5 种操作:
- 在最左侧插入一个数;
- 在最右侧插入一个数;
- 将第 k个插入的数删除;
- 在第 k 个插入的数左侧插入一个数;
- 在第 k 个插入的数右侧插入一个数
现在要对该链表进行 M次操作,进行完所有操作后,从左到右输出整个链表。
注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n个数,则按照插入的时间顺序,这 n 个数依次为:第 11 个插入的数,第 22 个插入的数,…第 n 个插入的数。
输入格式
第一行包含整数 M,表示操作次数。
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:
L x
,表示在链表的最左端插入数 x。
R x
,表示在链表的最右端插入数 x。
D k
,表示将第 k 个插入的数删除。
IL k x
,表示在第 k 个插入的数左侧插入一个数。
IR k x
,表示在第 k 个插入的数右侧插入一个数。
输出格式
共一行,将整个链表从左到右输出。
数据范围
1≤M≤100000
所有操作保证合法。
输入样例:
1 2 3 4 5 6 7 8 9 10 11
| 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
|
输出样例:
个人代码
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
| #include<bits/stdc++.h> using namespace std; struct node { int val; node* pre; node* next; node():val(0),next(nullptr),pre(nullptr){} node(int val):val(val),next(nullptr),pre(nullptr){} node(int val,node *pre):val(val),pre(pre),next(nullptr){} node(int val,node *pre, node* next):val(val),pre(pre),next(next){} };
node *leftNode; node *rightNode;
vector<node*>record;
void LI(int val,node *p) { node *leftT = p->pre; node *temp = new node(val,leftT,p); record.push_back(temp); leftT->next = temp; p->pre = temp; }
void RI(int val, node *p){ node *rightT = p->next; node *temp = new node(val,p,rightT); record.push_back(temp); rightT->pre = temp; p->next = temp; } void D(node *p) { node *r = p->next; node *l = p->pre; r->pre = l; l->next = r; } void say() { node* temp = leftNode; while(temp->next != rightNode){ temp = temp->next; printf("%d ",temp->val); } cout<<endl; }
int main() { record.push_back(nullptr); int n;cin>>n; rightNode = new node(-1); leftNode = new node(-1); rightNode->pre = leftNode; leftNode->next = rightNode; while(n--){ string op;cin>>op; int val;cin>>val; if (op[0] == 'R') { LI(val,rightNode); } else if (op[0] == 'L'){ RI(val,leftNode); } else if (op[0] == 'D') { D(record[val]); } else { int v;cin>>v; if (op[1]=='L') { LI(v,record[val]); } else { RI(v,record[val]); } } } say(); }
|
板子
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
| #include <iostream>
using namespace std;
const int N = 100010;
int m; int e[N], l[N], r[N], idx;
// 在节点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() { cin >> m;
// 0是左端点,1是右端点 r[0] = 1, l[1] = 0; idx = 2;
while (m -- ) { string op; cin >> op; int k, x; if (op == "L") { cin >> x; insert(0, x); } else if (op == "R") { cin >> x; insert(l[1], x); } else if (op == "D") { cin >> k; remove(k + 1); } else if (op == "IL") { cin >> k >> x; insert(l[k + 1], x); } else { cin >> k >> x; insert(k + 1, x); } }
for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' '; cout << endl;
return 0; }
|