![image-20220227131753050](http://imt.rui.vin/202202271318039.png)
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
这次删除的是链表,链表删除元素比较方便,但要注意元素边界
思路: 先提出剔除 链表前部分符合条件元素,找真正的起点
从起点开开始遍历,查看下一个元素是否符合,符合跳过,更改指针方向
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ListNode *removeElements(ListNode *head, int val) { while (head->next != nullptr && head->val == val) { head = head->next; } ListNode *cur = head; while (cur != nullptr && head->next != nullptr) { if (cur->next->val == val) { cur->next = cur->next->next; } else { cur = cur->next; } return head; } }
|
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表 (经典题目了)
思路1: 建一个虚拟的头节点,然后遍历链表,改变元素指针指向(指向虚拟节点)
思路2: 用栈的特性,遍历链表入栈,出栈一个一个链接起来
1 2 3 4 5 6 7 8 9 10 11 12
| ListNode *reverseList(ListNode *head) { ListNode * vhead = nullptr; ListNode *cur = nullptr; while (head != nullptr) { cur = head; head = head ->next; cur->next = vhead; vhead = cur; } return vhead; }
|
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
思路: 因为两两交换,所以每次都选两个节点,开始的时候用一个虚拟的节点作为头结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ListNode* swapPairs(ListNode* head) { if (head == nullptr) { return nullptr; } ListNode *dyHead = new ListNode(0); dyHead->next = head; ListNode *cur = dyHead; while (cur->next && cur->next->next) { ListNode *t1 = cur->next; ListNode *t2 =cur->next->next; t1->next = t2->next; t2->next = t1; cur->next= t2; cur = cur->next->next; } return dyHead->next; }
|
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
![img](http://imt.rui.vin/202203011232466.png)
思路: A 和 B 都同时走
若相交,链表A: a+c, 链表B : b+c
a+c+b+c = b+c+a+c 。则会在公共处c起点相遇。
若不相交,a+b = b+a 。因此相遇处是NULL
1 2 3 4 5 6 7 8 9
| ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode *fast = headA; ListNode *slow = headB; while (fast != slow) { fast = (fast != nullptr ? fast->next : headB); slow = (slow != nullptr ? slow->next : headA); } return fast; }
|
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
反转链表升级版
思路: 遍历链表到到 left的位置 以left 上一个节点为头结点,接下来遍历节点,以头插法的方式插入头结点上(此时问题 又转换到而来 反转链表 I 的问题,不同的是并不是遍历到尾)
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
| ListNode *reverseBetween(ListNode *head, int left, int right) { if(head->next == nullptr) return head; ListNode *vHead = new ListNode(0); vHead ->next = head; ListNode *p = vHead; ListNode *q = vHead->next; for (int i = 0; i < left-1; i++) { p = p->next; q = q->next; }
for (int i = 0; i < right - left; i++) { ListNode *temp = q->next; q->next = q->next->next; temp->next = p->next; p->next = temp; } return vHead->next; }
|
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
![image-20220407144530921](/C:/Users/hrp/AppData/Roaming/Typora/typora-user-images/image-20220407144530921.png)
思路: 每k个节点反转, 可以把问题拆分到 每组 k个节点的反转,最后将每组拼接起来,对于反转 一个链表比较容易,这次反转有指定得的范围,k个几点
利用递归可以将每组拼接起来
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
| class Solution { public: ListNode* reverseList(ListNode* head,ListNode* tail) { ListNode *vhead = new ListNode(); ListNode *v = vhead->next; while(head != tail){ ListNode *t = head->next; head->next = v; v = head; head = t; } return v; } ListNode* reverseKGroup(ListNode* head, int k) { ListNode *node = head; for(int i = 0;i < k; i++){ if(node == nullptr) return head; node = node->next; } ListNode *res = reverseList(head,node); head->next =reverseKGroup(node,k); return res; } };
|