LeetCode 206-反转链表
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
解题思路
判断:
- 我的思路:先遍历原链表,用数组将链表的val存下来,再用新的链表遍历创建新节点。(其实这是对内存空间的浪费。)
- 只需要改变链表的next指针的指向,直接将链表反转。具体做法:
- 先定义一个cur指针,指向头节点,再定义一个pre指针,初始化为null。
- 开始反转,把cur.next节点用tmp指针保存一下
- 循环走反转代码逻辑,继续移动pre和cur指针。
- 最后,cur指针指向null,循环结束,链表反转完毕。pre指针指向了新的头节点,返回pre指针。
可用双指针法、递归法。
- 双指针法
- 递归法
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
我的思路
用时14ms,消耗内存43.3M
class Solution {
public ListNode reverseList(ListNode head) {
int length = 0;
if (head == null) {
return null;
}
ArrayList<Integer> nums = new ArrayList<Integer>();
ListNode currentNode = head;
while (currentNode != null) {
nums.add(currentNode.val);
currentNode = currentNode.next;
length++;
}
ListNode headNode = new ListNode(nums.get(length-1));
ListNode revListcur = headNode;
for (int i = length-1; i > 0; i--) {
System.out.println(nums.get(i-1));
revListcur.next = new ListNode(nums.get(i-1));
revListcur = revListcur.next; //将节点连接起来
}
return headNode;
}
}
双指针法
0ms,41.6MB
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = null;
while(cur != null) {
ListNode tmp = cur.next;
cur.next = pre; // 翻转操作
pre = cur;
cur = tmp;
}
return pre;
}
递归法
0ms,41.3M
public ListNode reverseList(ListNode head) {
return reverse(null, head);
}
public ListNode reverse(ListNode pre, ListNode cur) {
if (cur == null) {
return pre;
}
ListNode tmp = null;
tmp = cur.next;
cur.next = pre;
pre = cur;
return reverse(cur, tmp);
}
复杂度
- 时间复杂度
- 我的思路: O(n)
- 双指针法: O(n)
- 递归法::O(n),要递归处理链表的每个节点
- 空间复杂度
- 我的思路:O(1)
- 双指针法:O(1)
- 递归法::O(n),递归调用了n层栈空间
难点
- 在原本链表的基础上直接反转:如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费。
- 双指针、递归思想的应用,可以提高代码效率。
总结
学习到新知识:递归方法。(还有一种从后向前递归的方法,以后再看)