赞
踩
为了明年的实习要从现在开始狠刷LeetCode了
这个反转链表在面试中还是经常容易考到的!!划重点
需求:反转一个单链表
1. 递归:
我在递归这方面一直都是比较弱的,所以我就以我最直白的方式来讲这个反转的递归,我自我觉得吧,我能看明白的递归大家应该都行(递归我是真不行),我这就直接说大白话了,能听懂就行,不讲那么官方了
我们首先看最初传入链表,头指针指向每一个节点,最后一个节点志向Null
我们需要将指针换成下图的这个样子
递归是从后往前
我们第一步是通过循环找到我们最后一个节点的位置
然后先建立一个新的链表newHead来保存我们反转的节点
到这一步我们新的链表头是不是就是5了,然后我们就需要让5去指向4,在下一次循环在4节点时,是不是4节点的next是5,我们又需要5节点的next是4,所以4节点的next的next就是4,这个时候我们就反转了两个节点,并且让尾结点变成4这个节点,所以4节点的next需要指向NULL(虚线是4节点next的指向),这个head是新链表的头
之后我们以此类推,往下反转
继续继续!!
这不就到最后一步了
这样我们就返回到头节点了,整个反转就完成啦,我虽然废话多了点,但是我觉得我应该说明白了吧
代码:::
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head; //链表为空直接返回,而head .next为空是递归基
int var=head.val;
ListNode newHead = reverseList(head.next); //循环到链尾
head.next.next = head; //翻转链表的箭头指向
head.next = null; //赋值NULL,防止链表错乱
return newHead; //返回新链表,新链表头永远指向的是原链表的链尾
}
迭代(非递归)
迭代这个循环就是从头开始的(下图是初始链表)
第一步先创建一个新链表,赋值为空(空的这个图我就没画啦)
ListNode newHead = null;
之后我们就需要循环的将我们初始链表的值一个一个追加在我们这个初始值为Null的新链表后面
步骤就拿第一个节点来举例,我们在完成第一步后会导致1节点与2节点的连接断开,我们需要做一个临时链表保存head.next,然后我们NewHead一开始是指向Null,现在我们让head.next节点(1节点)指向了NewHead(就相当于插进来当头节点),NewHead去指向Head,这个时候相当于我们去初始的节点中把1节点拽了过来,所以现在初始节点的头节点就成了2节点
(下面这个就解释一下head.next节点(1节点)指向了NewHead(就相当于插进来当头节点),NewHead去指向Head.next这句话)
(虚线是原本的指向,蓝色线是我们更改后的指向)
先添加第一个(旧链表的头结点在新链表的尾结点)
(这个图我在画的时候其实是少了一个头结点,还有这个图里面也少了那个临时变量的保存值,但是那个我画完没保存,这句话是我后面查看发现错误的,具体那个头他其实是我什么那个简笔画,第一次做这个算法的结构讲解还是有点问题,对不起大家!!!)
继续添加2节点到新链表
继续添加3节点到新链表
继续添加4节点到新链表
添加5节点到新链表(这样新链表就完成了,我们的反转也完成了,本质上还是进行指针的改变)
if (head == null || head.next == null) return head;
ListNode newHead = null; //链表为空直接返回,而head .next为空是递归基
while (head != null) { //一直迭代到链尾
ListNode tmp = head.next; //暂存一下下一个地址,防止指针变化的指向后找不到后续的数
head.next = newHead; //指向前一个空间
newHead = head; //新链表的头移动到head,扩长链表
head = tmp; //head指向初始链表head指向的下一个空间
}
return newHead;
可能说的比较废话,因为我一开始在递归哪就看大家的讲解有点模糊,如果还有不理解的留言吧!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。