题目:
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
解答:看懂了,但是自己写有问题,自己写的太多的判断了,直接看解答
//指定head,然后在k段内翻转,k段内都不为nullptr //head-开始的头结点 //tail-要翻转的最后一个节点 //返回:翻转后的头-尾节点 pair<ListNode*, ListNode*> reverseK(ListNode* head, ListNode* tail) { ListNode* pre = tail->next;//使用尾部的下一个元素作为头 ListNode* cur = head; ListNode* next = nullptr; while (pre != tail) { next = cur->next; cur->next = pre; pre = cur; cur = next; } return{ tail, head }; } ListNode* reverseKGroup(ListNode* head, int k) { ListNode* dummy = new ListNode(0); dummy->next = head; ListNode* pre = dummy; while (head != nullptr) { ListNode* tail = pre; for (int i = 0; i < k; i++) { tail = tail->next; if (tail == nullptr)//如果链表长度小于k,则直接返回该链表 return dummy->next; } ListNode* next = tail->next;//k段链表的下一个节点 pair<ListNode*, ListNode*> result = reverseK(head, tail); head = result.first; tail = result.second; //把k段的链表重新接回原链表 pre->next = head; tail->next = next; //更新pre head,用于下一段k的反转; pre = tail; head = tail->next; } return dummy->next; }
相关题目:
203-移除链表元素
206-反转一个链表
题目-206
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
解答:
代码一:迭代方法:
if (head == nullptr) return head; if (head->next == nullptr)//如果链表就一个节点,则直接返回 return head; ListNode* pre = nullptr; ListNode* cur = head; ListNode* next = nullptr; while (cur != nullptr) { next = cur->next; cur->next = pre; pre = cur; cur = next; } return pre;
}
方法二:递归:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode/
题目-203
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6 输出: 1->2->3->4->5
解答:
自己写的代码:
//链表中可能有多个符合的元素 ListNode* removeElements(ListNode* head, int val) { if (head == nullptr) return head; while (head!= nullptr && head->val == val) head = head->next; ListNode dummy; dummy.next = head; ListNode* tmp = &dummy; ListNode* pre = &dummy; while (tmp != nullptr) { tmp = tmp->next; while (tmp != nullptr && tmp->val == val) { tmp = tmp->next; } pre->next = tmp; pre = tmp; } return head; }
问题:上面的代码没有释放移除节点,需要delete,修改如下:
//上面的函数没有删除移除的节点, ListNode* removeElements2(ListNode* head, int val) { if (head == nullptr) return head; ListNode* toBeDelete = nullptr; while (head != nullptr && head->val == val) { toBeDelete = head; head = head->next; if (toBeDelete != nullptr) delete toBeDelete; } ListNode dummy; dummy.next = head; ListNode* tmp = &dummy; ListNode* pre = &dummy; while (tmp != nullptr) { tmp = tmp->next; while (tmp != nullptr && tmp->val == val) { toBeDelete = tmp; tmp = tmp->next; if (toBeDelete != nullptr) delete toBeDelete; } pre->next = tmp; pre = tmp; } return head; }
解答中的代码很简洁,如下,使用了一个哨兵sentinel,而且根据当前的cur的val是否为目标值对pre进行不同的处理,逻辑比自己写的简单:
ListNode* removeElements3(ListNode* head, int val) { ListNode* sentinel = new ListNode(0); sentinel->next = head; ListNode* pre = sentinel; ListNode* cur = head; ListNode* toBeDelete = nullptr; while (cur != nullptr) { if (cur->val == val) { pre->next = cur->next; toBeDelete = cur; } else pre = cur; cur = cur->next; if (toBeDelete != nullptr) { delete toBeDelete; toBeDelete = nullptr; } } ListNode* ret = sentinel->next; delete sentinel; return ret; }