有点意思,(汤老师说)上路子了小戴
目录
t->next=p->next; 此句引起错误的原因是,不应该使用即将释放的指针,直接这样写:t->next=t->next->next;
一个快指针(next两步)一个慢指针(next一步),如果环了肯定会相遇
21. 合并两个有序链表
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if(!l1) return l2;
else if(!l2) return l1;
struct ListNode *head=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode * t=head;
while (l1 && l2){
if (l1->val < l2->val){
t->next = l1;
l1 = l1->next;
}
else{//令人迷惑,这里要是加上else if的判断条件,就会出错??什么原理??
t->next = l2;
l2 = l2->next;
}
t = t->next;
}
if(l1) t->next=l1;
else t->next=l2;
return head->next;
}
83. 删除排序链表中的重复元素
t->next=p->next; 此句引起错误的原因是,不应该使用即将释放的指针,直接这样写:t->next=t->next->next;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head==NULL) return head;
struct ListNode *t=head,*p=NULL ;
while(t!=NULL&&t->next!=NULL){
if(t->next->val==t->val){ //判断条件前后顺序不同执行用时不同
p=t->next; //不写释放内存的语句会更快
// t->next=p->next;此句引起错误的原因是,使用空指针p,不应该用即将释放的指针
t->next=t->next->next;
free(p);
}else t=t->next;
}
return head;
}
141. 环形链表(快慢相遇)
一个快指针(next两步)一个慢指针(next一步),如果环了肯定会相遇
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
一个快指针(next两步)一个慢指针(next一步),如果环了肯定会相遇
*/
bool hasCycle(struct ListNode *head) {
if(!head) return false;
struct ListNode *slow=head,*fast=head;
while(slow&&fast&&fast->next){
slow=slow->next;
fast=fast->next->next;//不用担心越界,while条件里保证了可以访问到两个next
if(fast==slow) return true;
}
return false;
}
160 图解相交链表 C
-
消除长度差的思想是,让长的那个链表减去比短的链表多出的那一部分,使两链表长度相同,然后开始遍历
-
而大神的代码是增加一段距离,使两个新的链表长度相等,然后从起点同时遍历,不管在什么位置,两链表剩余长度都是相同的如图
-
pa pb一起出发,pa走完了a表就开始走b表,pb相同
当出现pa==pb时,说明出现了交点
### 解题思路
这里是对大神代码(复杂化)虽然更易懂(但是惭愧..))
意思是:
- pa pb一起出发,pa走完了a表就开始走b表,pb相同
- 当出现pa==pb时,说明出现了交点
### 代码
```c
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(!headA||!headB) return NULL;
struct ListNode *pa=headA,*pb=headB;
while(pa!=pb){//遍历判断相等吗?相等就是交点
// pa=pa == NULL?headB:pa->next;
// pb=pb == NULL?headA:pb->next;
pa=pa;//pa在变化所以每次重新赋值
if(pa==NULL) pa=headB;//如果pa是空的说明a表走完了,接下来走b表(pa变了)
else pa=pa->next;//如果pa不空说明a表没走完,那就继续走(pa变了)
pb=pb;
if(pb==NULL) pb=headA;
else pb=pb->next;
}
return pa;
}
203 移除链表元素(W)
解题思路
-
没有头结点的链表噢
-
如果上来的前面几个节点就是要删的节点,直接指针后移,并且改变头指针(删除开始节点)
-
如果不是开头的节点,那么(删除中间节点的方法)
-
如果没找到相等的节点,那么就一直找下去
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode *p=head;
while(p){
if(p->val==val){ p=p->next;head=p;}//删开头
else if(p->next&&p->next->val==val) p->next=p->next->next;//删中间
else p=p->next;
}
return head;
}