19. 删除链表的倒数第 N 个结点

难度中等1201
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?

  1. class Solution {
  2. public:
  3. ListNode* removeNthFromEnd(ListNode* head, int n) {
  4. //主要是因为单个元素的情况 所以要新开
  5. ListNode* dummpy = new ListNode(0, head);
  6. ListNode* p = dummpy;
  7. ListNode* q = dummpy;
  8. int t = n;
  9. //先遍历到尾部
  10. while(t --){
  11. p = p->next;
  12. }
  13. while(p->next != nullptr){
  14. p = p->next;
  15. q = q->next;
  16. }
  17. q->next = q->next->next;
  18. ListNode* ans = dummpy->next;
  19. delete dummpy;
  20. return ans;
  21. }
  22. };

25. K 个一组翻转链表

难度困难917
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例:
给你这个链表:1->2->3->4->5
k = 2 时,应当返回: 2->1->4->3->5
k = 3 时,应当返回: 3->2->1->4->5

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode() : val(0), next(nullptr) {}
  7. * ListNode(int x) : val(x), next(nullptr) {}
  8. * ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. class Solution {
  12. public:
  13. //局部翻转
  14. pair<ListNode*, ListNode*> Reverse(ListNode* head, ListNode* tail){
  15. ListNode* cur = head;
  16. ListNode* pre = tail->next;
  17. while(pre != tail){
  18. ListNode* next = cur ->next;
  19. cur->next = pre;
  20. pre = cur;
  21. cur = next;
  22. }
  23. return {tail, head};
  24. }
  25. ListNode* reverseKGroup(ListNode* head, int k) {
  26. ListNode* nhead = new ListNode(-1);
  27. nhead->next = head;
  28. ListNode* pre = nhead;
  29. while(head != nullptr){
  30. ListNode* tail = pre;
  31. //检测剩余节点是否满足小于k
  32. for(int i = 0; i < k; ++ i){
  33. tail = tail->next;
  34. if(tail == nullptr){
  35. return nhead->next;
  36. }
  37. }
  38. //缝合,整体更新
  39. ListNode* nex = tail->next;
  40. //局部翻转
  41. tie(head, tail) = Reverse(head, tail);
  42. //拼接
  43. pre->next = head;
  44. tail->next = nex;
  45. //更新值
  46. pre = tail;
  47. head = tail->next;
  48. }
  49. return nhead->next;
  50. }
  51. };

206. 反转链表

难度简单1522
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode() : val(0), next(nullptr) {}
  7. * ListNode(int x) : val(x), next(nullptr) {}
  8. * ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. class Solution {
  12. public:
  13. ListNode* reverseList(ListNode* head) {
  14. ListNode* cur = head;
  15. ListNode* pre = nullptr;
  16. while(cur != nullptr){
  17. ListNode* next = cur->next;
  18. cur->next = pre;
  19. pre = cur;
  20. cur = next;
  21. }
  22. return pre;
  23. }
  24. };

92. 反转链表 II

难度中等788
给你单链表的头指针 head 和两个整数 leftright ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表

示例 1:
链表1-快慢指针(删除倒数),反转问题 - 图1
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:
输入:head = [5], left = 1, right = 1
输出:[5]
提示:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n
  1. class Solution {
  2. public:
  3. ListNode* reverseBetween(ListNode* head, int left, int right) {
  4. ListNode* dummpy = new ListNode(-1);//1.这个用一下真的很方便
  5. dummpy->next = head;
  6. ListNode* nhead = head;
  7. ListNode* pre = dummpy;
  8. int idx = 1;
  9. //找到反转点
  10. while(nhead && idx < left){
  11. pre = nhead;
  12. nhead = nhead->next;
  13. idx ++;
  14. }
  15. //开始反转
  16. ListNode* npre = pre;
  17. ListNode* oleft = nhead;//2.保存反转后的尾节点,省掉很多操作
  18. ListNode* nbegin = nhead;
  19. while(nbegin && idx <= right){
  20. ListNode* nex = nbegin->next;
  21. nbegin->next = npre;
  22. npre = nbegin;
  23. nbegin = nex;
  24. idx ++;
  25. }
  26. oleft->next = nbegin;
  27. pre->next = npre;
  28. return dummpy->next;
  29. }
  30. };