剑指 Offer II 024. 反转链表https://leetcode.cn/problems/UHnkqh/
首先看到这道题的时候,首先想到的是双指针,一头一尾向中间 遍历,过程中交换他们节点的val值,后来写了两句代码发现,原来自己没睡醒,右边的指针怎么向中间靠拢哈哈哈。然后又想了另一种方法,用栈,不过需要遍历两次,暂时也想不出更好的办法了,决定先试试。
class Solution {
public ListNode reverseList(ListNode head) {
Stack<ListNode> stack = new Stack<>();
while (head!=null){
stack.push(head);
head=head.next;
}
ListNode newList = new ListNode(-1);
ListNode temp = newList;
while (!stack.Empty()){
temp.next = stack.pop();
temp=temp.next;
}
return newList.next;
}
}
写完之后测试用例发现是死循环,后来检查了一下代码,发现从栈里面取出来的最后一个节点,它的next仍然指向倒数第二个节点,经过遍历出栈后倒数第二个节点的next又指向最后一个节点,然后这里就变成了死循环。
还有一个问题,这里我判空方法用的是empty(),但这样写的话它报异常,实际上他还有另一个方法isEmpty(),之前以为这两个方法是相同的,知道做题的时候百度查了一下,发现isEmpty()实际上是调用Stack父类Vector的方法,返回的是elementCount == 0,而empty()是调用size()方法,返回的是elementCount,前者返回boolean类型,后者返回int类型,即栈内的节点数。后面经过修改后提交成功。
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null) return head;
Stack<ListNode> stack = new Stack<>();
while (head!=null){
stack.push(head);
head=head.next;
}
ListNode newList = new ListNode(-1);
ListNode temp = newList;
while (!stack.isEmpty()){
temp.next = stack.pop();
temp=temp.next;
}
temp.next=null;
return newList.next;
}
}
官方解法是使用双指针,一前一后改变箭头指向关系,这样不用开辟栈空间,也省去了新链表的空间,总的来说可以大大减少内存消耗。官方代码可以参考:
力扣https://leetcode.cn/problems/UHnkqh/solution/fan-zhuan-lian-biao-by-leetcode-solution-34oi/