重生之“我打数据结构,真的假的?”--2.单链表(完结)
1.链表的深拷贝
思路:
1.遍历原链表根据结点保存的数据,申请并复制到新的结点,并且插入到该节点后。
2.新结点的随机指向结点 = 原链表结点的随机指向结点的下一个结点!!
3.所有malloc的新节点全部连接起来
struct Node* copyRandomList(struct Node* head) {
struct Node* phead = NULL;
struct Node* flag = head;
struct Node* q = NULL;
struct Node* p = NULL;
if(head==NULL)
return q;
while (flag) {
q = NULL;
q = (struct Node*)malloc(sizeof(struct Node));
q->next = flag->next;
flag->next = q;
q->val = flag->val;
flag = q->next;
}
flag = head;
p = flag->next;
phead = p;
while (p->next) {
if (flag->random == NULL)
p->random = NULL;
else {
p->random = flag->random->next;
}
flag = p->next;
p = flag->next;
}
if (flag->random == NULL)
p->random = NULL;
else {
p->random = flag->random->next;
}
p=head->next;
while (p->next)
{
p->next=p->next->next;
p=p->next;
}
return phead;
}
2.环形链表||
思路
1.先判断是否有环
设快指针(一次走两步),慢指针(一次走一步)
若二者相遇则有环,若快指针走到NULL;则无环
2.标记快慢指针相遇处,为p
设q为头;!!!!!!!
在p与q相遇前 p=p->next;q=q->next;
3. p,q相遇时p为入口处;
struct ListNode *detectCycle(struct ListNode *head) { struct ListNode * p=head; struct ListNode * q=head; if(p==NULL||p->next==NULL) //判断是否有环 return NULL; do { p=p->next; q=q->next->next; if(q==NULL||q->next==NULL) return NULL; }while(p!=q);//判断是否有环 p=head; while(p!=q) { p=p->next; q=q->next; } return p; }
3.错题反思
原思路:
1.实在想不到什么好办法;如果从a链表首节点开始,每次遍历一遍b表找第一个相同节点太耗费时间,意义不大。
2.也想过建立两个栈,让a,b各节点进栈,根据栈的后进先出从尾出栈开始比。
答案思路(nb!!!)
1. 如果两链表有共同节点
设a表头到共同节点的距离为x;
b表头到共同节点的距离为y;
共同节点到NULL的距离为n;
2.while(a!=b)
遍历a,b链表;
当a为NULL,a=headb;
当b为NULL,b=heada;
3.a与b必然在共同节点处相遇
因为a走的距离为:x+n+y;
b走的距离为:y+n+x;
4.
以a为例:
a走完x+n步后,变为headb,再走y步正好为共同节点处
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *A = headA;
struct ListNode *B = headB;
while (A != B) {
A = A ? A->next : headB;
B = B ? B->next : headA;
}
return A;
}