两两交换链表节点:
tips:
1.用dummy head
2.cur->dummy head,原因见下图,操作1,2的交换需要dummyhead先指向2,2再指向1
3.while里面一定要先写cur->next=NULL&&cur->next->next=NULL,反过来写,如果cur->next为空就会报错
4.对节点2进行操作时要用temp和temp1保存节点1和节点3的指针(原因见视频)
5.最后要移动cur的操作
删除链表倒数第n个节点:
tips:
思路:定义一个快指针和一个慢指针指向dummyhead,然后让快指针先移动n+1步,然后快慢指针同时移动,直到快指针指向NULL为止,这时慢指针恰好指向倒数第n个节点的前一个节点(这也是快指针移动n+1步而非n步的原因)
1.注意最后return dummyhead的next
没太搞懂下面for循环i++如何避免fast->next是空节点??
/**c语言单链表的定义
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
//定义虚拟头节点dummy 并初始化使其指向head
struct ListNode* dummy = malloc(sizeof(struct ListNode));
dummy->val = 0;
dummy->next = head;
//定义 fast slow 双指针
struct ListNode* fast = head;
struct ListNode* slow = dummy;
for (int i = 0; i < n; ++i) {
fast = fast->next;
}
while (fast) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;//删除倒数第n个节点
head = dummy->next;
free(dummy);//删除虚拟节点dummy
return head;
}
环形链表:
①判断链表是否有环:
tips:
1.定义一个快指针一个慢指针,入环后快指针和慢指针一定会相遇
注:快指针每次移动2个节点,慢指针每次移动1个节点,这样才能保证快慢指针一定会相遇(若快指针每次移动3节点就有可能永远错过)
2.
②判断入口位置:
tips:
1.重要关系:x=(n-1)(y+z)+z
也就是说,可以定义两个移动速度相同的指针,一个从head出发,一个从相遇点出发,二者在入口相遇
代码实现:
while里面要先判断快指针不为空且快指针的下一个不为空(因为快指针一次跳两步)
定义相遇点(此时的fast)为指针index1;开始处为指针index2