LeetCode Reverse Linked List翻转链表

Reverse a singly linked list.

       题目只有一句话,刚看到这道题时觉着没有什么难度,通过集合类LinkedList提供的一些方法先遍历再进行反向插入就好了,然看到题目给出的方法才知道它是不能使用集合类的,只能通过自定义的链表实现翻转。然后就有点懵了,可能是自己链表、指针方面的知识有点薄弱吧,想了好久没有思路,去网上查了查资料,觉着这道题真心不错,至少可以巩固扎实自己的基础知识,也让我认识到了自己的这方面的不足,尤其是对递归而言,理解起来会比较困难,怎样去弥补呢,自然是多做一些递归方面的题培养自己递归解决问题的思想了,额额......

这道题呢,算是面试中比较经典的题了,它有两种解法递归和迭代,个人觉着迭代比较简单,递归的话翻转指针来说一开始没能够理解,现在多用断点调试再想一下就差不多了,这里我先给大家分享一下这两种方法的思想。

迭代方式

       迭代的方式是从链头开始处理,如下图给定一个存放5个数的链表。


这里写图片描述

  首先对于链表设置两个指针:

这里写图片描述

  然后依次将旧链表上每一项添加在新链表的后面,然后新链表的头指针NewH移向新的链表头,如下图所示此处需要注意,不可以上来立即将上图中P->next直接指向NewH,这样存放2的地址就会被丢弃,后续链表保存的数据也随之无法访问。而是应该设置一个临时指针tmp,先暂时指向P->next指向的地址空间,保存原链表后续数据。然后再让P->next指向NewH,最后P=tmp就可以取回原链表的数据了,所有循环访问也可以继续展开下去

这里写图片描述
  指针继续向后移动,直到P指针指向NULL停止迭代。

这里写图片描述
  最后一步:

这里写图片描述

       下面是我自己的Java实现......

package com.gaoxue.LeetCode;

class ListNode{
	int val;
	ListNode next;
	public ListNode(int val) {
		this.val = val;
	}
}
public class ReverseList {

	public ListNode reverseList(ListNode head) {
		ListNode newHead = null;
		while(head!=null) {
	        ListNode temp = head.next;
	        head.next = newHead;
	        newHead = head;
	        head = temp;
		}
		return newHead;
    }
	public static void main(String[] args) {
		ListNode head = null;
		ListNode dummy = null;
		int x[] = new int[] {1,2,3,4,5};
		for(int i=0;i<x.length;i++) {
			if(head==null) {
				head = new ListNode(x[i]);
				dummy = head;
			}else {
				dummy.next = new ListNode(x[i]);
				dummy = dummy.next;
			}
		}
		ListNode head2 = new ReverseList().reverseList(head);
		while(head2!=null) {
			System.out.print(head2.val+" ");
			head2 = head2.next;
		}
	}
}

递归方式

       首先指针H迭代到底如下图所示,并且设置一个新的指针作为翻转后的链表的头。由于整个链表翻转之后的头就是最后一个数,所以整个过程NewH指针一直指向存放5的地址空间。


这里写图片描述
  然后H指针逐层返回的时候依次做下图的处理,将H指向的地址赋值给H->next->next指针,并且一定要记得让H->next =NULL,也就是断开现在指针的链接,否则新的链表形成了环,下一层H->next->next赋值的时候会覆盖后续的值。

这里写图片描述
  继续返回操作:

这里写图片描述
  上图第一次如果没有将存放4空间的next指针赋值指向NULL,第二次H->next->next=H,就会将存放5的地址空间覆盖为3,这样链表一切都大乱了。接着逐层返回下去,直到对存放1的地址空间处理。

这里写图片描述
  返回到头:

这里写图片描述

       下面是我的Java实现......

package com.gaoxue.LeetCode;

class ListNode{
	int val;
	ListNode next;
	public ListNode(int val) {
		this.val = val;
	}
}
public class ReverseList {

	public ListNode reverseList(ListNode head) {
        if(head==null||head.next==null) {
        	return head;
        }
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
	public static void main(String[] args) {
		ListNode head = null;
		ListNode dummy = null;
		int x[] = new int[] {1,2,3,4,5};
		for(int i=0;i<x.length;i++) {
			if(head==null) {
				head = new ListNode(x[i]);
				dummy = head;
			}else {
				dummy.next = new ListNode(x[i]);
				dummy = dummy.next;
			}
		}
		ListNode head2 = new ReverseList().reverseList(head);
		while(head2!=null) {
			System.out.print(head2.val+" ");
			head2 = head2.next;
		}
	}
}
       我觉着大家根据图解再去了解代码会明确很多,两种方式都很值得学习,我们应该花较长的时间去内化掌握它,再接再厉哈...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值