反转链表

浅浅的花香味﹌ 2022-05-13 22:45 411阅读 0赞

题目描述

输入一个链表,反转链表后,输出新链表的表头。

链表的数据结构如下:

  1. public class ListNode {
  2. int val;
  3. ListNode next = null;
  4. ListNode(int val) {
  5. this.val = val;
  6. }
  7. }

[反转链表]也叫做[链表逆置].比如一个链表是这样的:1->2->3->4->5,通过反转后可以变成为5->4->3->2->1。

容易想到的方法遍历一遍链表,利用三个指针,第一个指针P存储反转的节点,第二个指针q存储当前的节点,反转前p—>q,反转后q—>p,第三个指针temp存储q节点的下一个节点用于遍历。代码如下:

第一种方法遍历求解反转链表问题:

  1. public class Solution {
  2. public static void main(String[] args) {
  3. //构造树结构测试用
  4. ListNode a = new ListNode(1);
  5. ListNode b = new ListNode(2);
  6. ListNode c = new ListNode(3);
  7. ListNode d = new ListNode(4);
  8. ListNode e = new ListNode(5);
  9. a.next = b;
  10. b.next = c;
  11. c.next = d;
  12. d.next = e;
  13. System.out.print("BeforeReverse: ");
  14. visit(a);
  15. System.out.println();
  16. Long begintime = System.nanoTime();
  17. ListNode f = ReverseList(a);
  18. Long endtime = System.nanoTime();
  19. System.out.print("AfterReverse: ");
  20. visit(f);
  21. System.out.println();
  22. System.out.print("ReverseTime = "+(endtime - begintime)+"ns");
  23. }
  24. public static void visit(ListNode p) {
  25. while(p!=null) {
  26. System.out.print(p.val + " ");
  27. p = p.next;
  28. }
  29. }
  30. public static ListNode ReverseList(ListNode head) {
  31. ListNode p = null;
  32. ListNode q = head;
  33. ListNode temp = null;
  34. while(q!=null){
  35. temp = q.next;
  36. q.next = p;
  37. p = q;
  38. q = temp;
  39. }
  40. return p;
  41. }
  42. }

程序运行的结果:

70

遍历求解反转链表的时间复杂度为O(n)

这个问题也可以使用递归求解。只需要修改ReverseList( )里面的内容就可以,其他的地方不用变。

第二种方法递归求解反转链表问题:

  1. public static ListNode ReverseList(ListNode head) {
  2. //如果链表为空或者链表中只有一个元素
  3. if(head == null || head.next == null)
  4. {
  5. return head;
  6. }
  7. else
  8. {
  9. //先反转后面的链表,走到链表的末端结点
  10. ListNode newhead = ReverseList(head.next);
  11. //再将当前节点设置为后面节点的后续节点
  12. head.next.next = head;
  13. head.next = null;
  14. return newhead;
  15. }
  16. }

在这里使用递归实现链表的反转是非常巧妙的一种解法,它利用递归走到链表的末端,然后再更新每一个node的next 值 ,实现链表的反转。

这里还是以链表:1->2->3->4->5为例。第一次走到末端时head指向4。

第一步:newhead走向链表的结尾,指向的是链表的最后一个节点,此时head.val = 4,newhead.val = 5;

第二步:head.val = 4,head.next.val = 5,head.next.next = head就实现了链表的反转,把4—>5变为5—>4。

第二步: head.next = null,就是把节点4的下一个节点指向null。

一个节点处理完了再通过递归回溯,此时的head指向的节点的值变成了3。

第一步:newhead就是head的下一个节点,此时head.val = 3,newhead.val = 4;

第二步:head.val = 3,head.next.val = 4,head.next.next = head就实现了链表的反转,把3—>4变为4—>3。

第二步: head.next = null,就是把节点3的下一个节点指向null。

依次类推。到反转的最后一个节点它的下一个节点的值因为设置了 head.next = null语句,可以把它的next指向空。所以整个逻辑是没有问题的。

程序运行结果:

70 1

递归求解反转链表的时间复杂度也是O(n)

发表评论

表情:
评论列表 (有 0 条评论,411人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    题目 给定一个常数K以及一个单链表L,请编写程序将L中每K个结点反转。例如:给定L为1→2→3→4→5→6,K为3,则输出应该为3→2→1→6→5→4;如果K为4,则输出

    相关

    时间限制:1秒 空间限制:32768K 热度指数:408664 本题知识点: 链表 算法知识视频讲解 题目描述 输入一个链表,反转链表后,输出新链表的表头。