001链表反转

今天是刷题的第一天,主要看的是牛客网数据结构和算法的题目。第一个讲的是链表反转的算法,利用数据结构堆栈和链表的特性。
堆栈的特性是先进后出,具体的内容可以参考博文:
添加链接描述 算法数据结构基础——堆栈
主要讲解了堆栈这种数据结构的特性主要是后进先出,就例如米桶一样,把所有的米粒倒进去之后,后倒进去的先打出来吃。这和堆栈的形式差不多,后进堆栈的数据先取出来。然后所有针对堆栈内的数据的操作都是在堆栈顶部进行的,无论是取数据还是压入数据,或者判断堆栈是否为空,堆栈是否为满都在堆栈顶部来进行处理和判断。

堆栈常用运算

create 创建一个新的堆栈空间
push 向堆栈内部压入数据
pop 将堆栈顶部的数据取出来
isEmpty 判断堆栈是否为空,如果是空就返回true,如果堆栈不为空就返回false
full 判断堆栈是否为满,如果堆栈满了的话就返回true,如果堆栈没有满就返回false

题目描述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。

数据范围: 0<=n<=100
要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) 。

如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
转换过程
反正我之前学编程的时候就没咋恩么认真学过,看到这种题目我也没什么思路,就直接找答案解析看了。
意思就是这个题目可以直接用反转链表的模型来解决,把每一个数据看做是链表的一个节点,然后转换数据之间的顺序就用堆栈的特性来进行数据顺序的轮转。
第一个节点装的数据是1,然后后面跟一个指针指向下一个数据的地址,next指向第二个链表的节点,第二个节点里面装的是数据2,数据2 后面在跟一个指针只想第三个数据节点的地址,第三个数据节点里面装的数据是3,后面跟一个指针指向下一个节点的首地址,如果没有后面的链表节点那next指向的就是null。
可以参照这张图:
在这里插入图片描述
然后链表在计算机中的存储是在堆栈中进行存储的,利用堆栈的基本运算pop和push来做数据的压入和数据的取出。
数据装入之后可以看到是按照输入的顺序放进去的,输入的第一个数据是1,所以堆栈底部的数据就是1,其次输入的第二个数据是2,所以堆栈中底部往上走的一个数据就是2,第三个放入堆栈的是3,所以堆栈的最顶层数据就是3。
再将堆栈内的数据取出的时候,第一个取出来的就是堆栈顶部的3,其次是2,最后是1。
逻辑很清楚了,该用什么数据结构和算法也很清楚了,接下来就是代码的实现了。反正写代码是我最讨厌的事情。直接看源码。

import java.util.Stack;

//这里是引入stack这个数据结构
public class Solution {
public ListNode ReverseList(ListNode head) {//这里给的参数是链表节点的首地址
Stack stack= new Stack<>();//新建一个stack数据结构,然后给定的对象名是stack,数据结构的类型是Stack,这个双箭头里面给的参数就是链表的首地址,然后括号里面表示对这个对象的操作;
//把链表节点全部摘掉放到栈中
while (head != null) {//当链表头的地址不为空的时候,表示这个链表里面还有数据,指向的下一个节点不为空
stack.push(head);//将head参数指向的这个节点通过push操作将数据压到堆栈里面去;
head = head.next;//把数据压到堆栈里面之后,指针指向下一个链表节点的表头;
}
if (stack.isEmpty())//这里判断堆栈是否为空,如果堆栈空的话就表示刚刚的链表全是空的,堆栈里面一个数据都没有,返回的数值也只能为空;如果堆栈里面不是空的说明链表里面是有数据的,有数据的话就要用pop运算将堆栈里面的数据取出来,执行一条之后的那些操作
return null;
ListNode node = stack.pop();//这里新建一个链表用来存储堆栈中取出来的数据
ListNode dummy = node;//dummy这里是什么东西不是很清楚,这个应该是指针用来指向链表首节点的首地址,因为输出数据的时候是输出指针指向的地址,所以这里dummy就是用来表示node节点的地址
//栈中的结点全部出栈,然后重新连成一个新的链表
while (!stack.isEmpty()) {//这里判断堆栈里面的数据是不是都取出来了,如果堆栈不为空的话就执行下面的操作
ListNode tempNode = stack.pop();//堆栈中取出的数据存放在tempNode当中
node.next = tempNode;//每个节点的next指向的就是这个取出来的数据的地址
node = node.next;//然后这里的node节点指向下一个链表节点,继续取出堆栈中的下一个数据
}
//最后一个结点就是反转前的头结点,一定要让他的next
//等于空,否则会构成环
node.next = null;//最后链表的下一跳指向null说明堆栈中的数据都取出来了
return dummy;//最终返回的值是dummy这个地址,也就是这个链表的首地址,输出的内容就是链表中的数据
}
}`

这个代码一共包含几个板块
首先是定义一个堆栈的空间
然后定义一个链表的对象,把输入值的首地址作为参数代入到链表中,将输入值的第一位作为链表节点中的数据压到堆栈中,然后输入值的首地址参数指向链表的下一个节点的首地址,循环往复,将链表中所有的数据都放到堆栈中。
然后根据实际情景判断这个链表和堆栈的情况是否为空,再决定相对应的返回值。
最后定义一个输出的链表,以及这个链表的首地址dummy,所有堆栈中取出的数据都放在这个输出链表中,对堆栈进行判断,如果为空的话就停止pop操作。
最后输出链表的最后一个节点指向的地址一定要给null,否则会形成环,将其他的数据一起带出来。
然后输出的结构就是返回这个输出链表的首地址dummy,自动会输出这个链表中的数据。
让我讲我可以很清楚的分析这个代码和题目的逻辑,但是让我复现一次源代码还是挺难的,我顶多写一下伪代码。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值