第二讲 线性表
1. 将具有线性关系的数据存储到计算机中所使用的存储结构称为线性表。
2. 对于线性表中的数据来说,位于当前数据之前的数据统称为“前趋元素”,前边紧挨着的数据称为“直接前趋”;同样,后边的数据统称为“后继元素”,后边紧挨着的数据称为“直接后继”。
3. 线性表的分类
(1) 数据元素在内存中集中存储,采用顺序表示结构,简称“顺序存储”;
例如:数组
(2) 数据元素在内存中分散存储,采用链式表示结构,简称“链式存储”。
例如:单链表、双链表、循环单(双)链表
4. 不同实现方式的时间复杂度(不要硬背结论、要从实现方式入手分情况讨论,下述为特定情况下的时间复杂度)
(1) 数组:随机索引O(1)、插入O(n)、删除O(n)
(2) 单链表:查找某一元素O(n)、插入O(1)、删除O(n)
(3) 双链表:查找某一元素O(n)、插入O(1)、删除O(1)
5. 考题:、2016-2、2012-42、2015-41、2019-41
2016-1
c a e b d NULL
? f
2016-2
2012-42
acwing 66 两个链表的第一个公共结点
c++:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) {
auto p = headA;
auto q = headB;
while(p!=q){
if(p)
p = p->next;
else p = headB;
if(q)
q = q->next;
else q = headA;
}
return p;
}
};
c:
struct ListNode *findFirstCommonNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *p = headA;
struct ListNode *q = headB;
while(p!=q){
if(p){
p= p->next;
}else p = headB;
if(q){
q= q->next;
}else q = headA;
}
return p;
}
2015-41
删除节点
acwing 3756. 筛选链表
c++:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* filterList(ListNode* head) {
bool stu[10000+5]={false};
stu[abs(head->val)] = true;
for(auto p = head; p->next ;){
auto t = abs(p->next->val);
if(stu[t]){
// 已经存在,删除
auto q = p->next;
p->next = q->next;
delete q;
}else{
// 不存在,
stu[t] = true;
p = p->next;
}
}
return head;
}
};
c:
struct ListNode* filterList(struct ListNode* head) {
bool stu[10000+5] = {false};
stu[abs(head->val)] = true;
for(struct ListNode *p = head ; p->next ;){
int x = abs( p->next->val );
if(stu[ x ] )
{
struct ListNode *q = p->next;
p->next = q->next;
free(q);
}else{
stu[x] = true;
p=p->next ;
}
}
return head;
}
2019-41
acwing 3757. 重排链表
c++:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void rearrangedList(ListNode* head) {
// 如果链表只有一个元素 , 不用处理直接打印
if(head->next == NULL) return ;
// 链表长度
int n = 0;
for(auto t = head;t;t =t->next){
// cout<<head->val;
n++;
}
// cout<<n<<endl;
// 前半段的结点数, 链表分为2段 1~mid-1 , mid ~ n;
int mid = (n+1)/2;
auto a = head;
for(int i=0;i<mid-1;i++)a=a->next;
auto b =a->next;
auto c = b ->next;
a->next = NULL;
b->next = NULL;
// 翻转 mid ~ n 到n~mid;
while(c){
// 预存后面的节点地址
auto t = c->next;
c->next = b; // 翻转
//b,c 后移一位
b = c;
c = t;
}
// 1~mid-1与 n ~ mid 合并 b此时已经到最后一个节点,c是NULL
for(auto p = head, q= b; q; ){
// 预存q->next 的节点
auto t = q->next ;
//p与q连接
q->next = p->next;
p->next = q;
// p,q 后移
p = q->next; // or p=p->next->next 此时这里 p->next就是q
q= t ; // q 到之前预存的t的位置
//循环实现,达到合并
}
return;
}
};
c:
void rearrangedList(struct ListNode* head) {
if(head->next == NULL) return ;
int n = 0;
for(struct ListNode* t = head;t;t =t->next){
n++;
}
int mid = (n+1)/2;
struct ListNode* a = head;
for(int i=0;i<mid-1;i++)a=a->next;
struct ListNode* b =a->next;
struct ListNode* c = b ->next;
a->next = NULL;
b->next = NULL;
while(c){
struct ListNode* t = c->next;
c->next = b;
b = c;
c = t;
}
struct ListNode* q= b;
for(struct ListNode* p = head; q; ){
struct ListNode* t = q->next ;
q->next = p->next;
p->next = q;
p = q->next;
q= t ;
}
return;
}
|