【链表】反转一个单向链表

在这里插入图片描述

第一步:定义一个单向链表

 public class ListNode {
       //用来存放当前节点的数据值
       int val;
       //用来指向下一个节点的引用,其实说的C里面的指针就是Java中的引用。
       因为我们如何来让一个个对象在内存关联起来,需要通过引用地址来依赖。
      ListNode next;
      //value数据值的赋值直接通过构造函数赋值,不需要set
      ListNode(int x) { val = x; }
 }

思考思路:
1、反转的边界条件:1个数据都没有的情况,只有2个的情况
在这里插入图片描述
那么我们先来看下默认情况下的链表,根据上面的类构造出的对象,在内存中是不连续分配的为什么不连续呢?有人思考过没有,因为他们都有自己的特定的引用地址。那么链表的意义是什么呢?就是将一个个对象像一个链子一样串联起来。形成一个数据结构。这样的话是不是好理解了?那么以我而言老师们整天说指针,我以为必须学好C语言,实际上目前来看Java语言你也可以理解这些数据结构。比如说指针的移动其实就是引用地址的赋值改变。比如我上面的图你可以看到的是有跟线没有按照正常的连接,导致那个线很长,实际上我只是形象话的画图而已。相当于如果正常的逻辑是依次连接很规整,但是实际上如果我们中间插入节点,或者删除节点,那么就可能导致这样的情况。第二个value值存储的是相当于自己本身的值,next属性其实相当于存储的是下个节点的引用地址,通过这样的依赖,形成一个链表。

那么代码我们怎么来实现呢?通过上面的图解我们可以编码按照刚才的思路,边界检查,代码书写。
在这里插入图片描述
在这里插入图片描述
现在我们用代码实现下上面的思路:

public ListNode reverseListNode(ListNode head){
//1、定义一个新的头节点信息初始为null
ListNode prev = null;
//2、定义能够拆分链表为2端的当前游标节点,开始的时候为首节点head;
ListNode curr = head;
//3、我们根据思路需要一个个节点进行迭代,基于上面的图解我们知道其实通过一个head节点就可以获取所有的信息只要不断next就可以,如果next没有引用为null说明走到了尾节点。
while(curr.next != null){
//根据上面讲的1-》2和2-》1我们知道会截断2部分,这个时候需要缓存临时变量部分,防止引用断开,我们找不到可达性gcroot分析找不到就被GC了
ListNode tempHead = curr.next;
//现在我们拆分为2部分,一部分为curr,一部分为curr.next现在称为tempHead;
//将新的头节点信息赋值给当前节点的引用,第一次是将curr的next置为null,第二次直接将新的链表赋值给当前游标节点
curr.next =prev;
//交换数据,现在的状态其实相当于图的第二步骤后的效果图,然后为了省略掉第三步骤,这里做了个小变动就是直接将当前这个游标节点赋值给prev新的头节点。这样就少了一步赋值
prev = curr;
//完成了上面的交换,
步骤第一次循环:现在分为2部分,prev: 1-》null, tempHead: 2-》3-》4-》5-》null
步骤第二次循环:现在分为2部分交换的时候相当于2与1的交换,prev: 2-》1-》null, tempHead: 3-》4-》5-》null
步骤第三次循环:现在分为2部分交换的时候相当于2与1的交换,prev: 3-》2-》1-》null, tempHead: 4-》5-》null
步骤第四次循环:现在分为2部分交换的时候相当于2与1的交换,prev: 4-》 3-》2-》1-》null, tempHead:5-》null
步骤第五次循环:现在分为2部分交换的时候相当于2与1的交换,prev: 5-》4-》3-》2-》1-》null, tempHead: null
步骤第六次循环:由于null退出循环条件。
//为了遍历下一个节点则我们这边重新定义当前的游标节点为tempHead
curr = tempHead;
}
//当所有的步骤都完成以后,我们就知道了prev是我们需要的东西。
return prev;
}
时间复杂度:O(n),空间复杂度:O(1);

这里是引用

//递归代码
public ListNode reverseListNode(ListNode head){
//递归主要需要做好边界处理
if(head == null || head.next == null){
return head;
}
//虚拟栈递归
ListNode newHead = reverseListNode(head.next);
//出栈倒序执行,用指针引用指向头尾相连,然后干掉原来的每个栈的首节点,则每个栈的首节点变为尾节点。
head.next.next = head;
head.next =null;
//最后只需要返回新的节点就可以啦。
return newHead;

}
时间复杂度O(n),因为我刚才图上也讲了需要用到虚拟栈,所以空间复杂度为O(n)

原题:反转一个单向链表

发布了213 篇原创文章 · 获赞 258 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/wolf_love666/article/details/94616818