作业感受
题目地址: https://leetcode-cn.com/leetbook/read/linked-list/f58sg/
一看题目,要求用两种解法实现,循环或者递归,我的内心还是喜欢递归的,于是先实现递归。
递归版作业
class Solution {
public ListNode reverseList(ListNode head) {
// 处理特殊条件
if(head == null) return null;
if(head.next == null) return head;
// 如果没有特殊情况,还是用双指针解决问题,快指针比慢指针多走一步
ListNode slow = head, fast = head.next;
//给返回的链表一个虚拟头部
ListNode dummyHead = new ListNode(5001);
// 快指针走到链表尾部,慢指针指向倒数第二个节点
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
//在head中删除最后一个节点
slow.next = null;
// 递归逆序排列
dummyHead.next = new ListNode(fast.val, reverseList(head));
return dummyHead.next;
}
}
递归作业表现
递归还是很消耗内存的啊
循环版作业
循环的感觉比递归要难一些,一开始我用了一个嵌套循环结构,让快指针到链表尾部,提取尾部元素后删除尾部,再返回头部,到达新的尾部,重复之前的操作。不出意料,果然运算超时了。
后来我想到,其实逆序排列就是顺序把元素插到原来链表的头部,这样事情就简单啦,慢指针指向头元素,快指针顺序向后走。中间调试指针的指向花了好久,逻辑还是不清晰,必须在纸上画然后试错。基本功啊,还是要努力!
功夫不负有心人,还是找到了正确结果。
class Solution {
public ListNode reverseList(ListNode head) {
// 处理特殊情况
if(head == null) return null;
if(head.next == null) return head;
// 处理一般情况,利用虚拟头节点
ListNode dummyHead = new ListNode(5001);
dummyHead.next = head;
ListNode slow = head, fast = head;
while(fast.next != null && slow.next != null){
fast = fast.next;
slow.next = fast.next;
// 将fast所指节点插到头节点后面
dummyHead.next = new ListNode(fast.val, head);
head = dummyHead.next;
}
return dummyHead.next;
}
}
循环版作业表现
关于内存消耗比较高这件事,我也试过去掉dummyHead, 但是行不通啊,不知道大家都是用了什么办法降低内存消耗的。