记录代码随想录 206.反转链表。
题目:给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
这里使用双指针来对链表进行反转,时间复杂度为O(n),空间复杂度为O(1)。
要更好理解如何用双指针来反转链表,就得画图。这里先放上代码随想录里的动图(纠正:动画应该先移动pre,再移动curr)。
首先是初始化,有current、pre两个指针。current指向当前操作的节点,开始肯定指向头节点;pre指向current的前一个节点,他将会是反转后current的next节点。
开始反转。首先保存current.next 节点为temp,其次current.next 赋值为pre,此时就已经反转了一个节点了。然后将pre 和current 向右移动,即pre 赋值为current,current赋值为temp,进入下一循环继续反转节点。注意操作顺序,不能乱。
下面是反转过程中的示图,可以模拟一下上面的4个过程:
代码如下:
ListNode current = head;
ListNode pre = null;
ListNode temp = null;
while (current != null) {
temp = current.next;
current.next = pre;
pre = current;
current = temp;
}
return pre; // 最后current==null结束,而pre就指向反转后链表的头节点
此外,递归法 也可以解决。
———————————————————————————————————————————
题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
这道题正常模拟就可以了,注意在奇数个节点时,最后那个节点不需要交换。
采用虚拟头节点,避免单独处理头节点。
在交换节点时,一定要画图理解,否则操作多个指针很容易乱,且要注意操作的先后顺序。
初始时,进行如下三步骤:cur.next 指向2,2的next 指向1,1的next 指向3。可见,需要2个临时变量来记录节点1 和3。
操作之后,链表如下:
看这个可能更直观一些:
代码如下,注释和上图中的三步骤对应:
ListNode dummyHead = new ListNode(-1, head); // 虚拟头节点
ListNode temp1 = null; // 临时变量1
ListNode temp2 = null; // 临时变量2
ListNode current = dummyHead;
while(current.next != null && current.next.next != null) {
temp1 = current.next;
temp2 = current.next.next.next;
current.next = current.next.next; // 步骤一
current.next.next = temp1; // 步骤二
current.next.next.next = temp2; // 步骤三
current = current.next.next; // 移动current,准备下一次交换
}
return dummyHead.next;