学习目标:
按照学习计划坚持刷完剑指offer 2
学习内容:
1、 剑指offer24:反转链表
2、 剑指offer25:链表中的两数相加
3、 剑指offer26:重排链表
学习产出:
第一题:
难度:简单
方法一:迭代
首先,理清思路:
链表为空,返回头节点
定义两个节点pre为null ,cur指向头节点
遍历链表时,定义临时节点存放cur的下一结点,同时让cur 指向pre
向后遍历,pre向后移到cur的位置,cur移到刚刚定义的临时节点位置(达到链表反转效果) ...(以此循环)
最后因cur == null跳出循环,pre在cur的前一位,所以返回pre即可
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null)return head;
ListNode pre=null;
ListNode cur=head;
while(cur!=null){
ListNode tmp=cur.next;
cur.next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
}
时间复杂度:O(n),其中 n 是链表的长度。需要遍历链表一次。
空间复杂度:O(1)。
方法二:递归
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
时间复杂度:O(n),其中n是链表的长度。需要对链表的每个节点进行反转操作。
空间复杂度:O(n),空间复杂度主要取决于递归调用的栈空间,最多为n层。
第二题
难度:中等
先把两个链表反转后再相加,因为从低位开始做加法比较直观,加法运算完成后再反转整个链表后返回。
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
l1 = reverse(l1);
l2 = reverse(l2);
ListNode ans = new ListNode(0);
ListNode cur = ans;
ListNode p1 = l1, p2 = l2;
int sum = 0, carry = 0;
while(p1 != null || p2 != null){
int x = (p1 == null ? 0:p1.val);//链表不为空就将当前的两个节点的值加起来,为空就加0
int y = (p2 == null ? 0:p2.val);
sum = x+y+carry;
carry = sum / 10;
//如果有进位,则carry余1, 没有进位则carry重置为0
ListNode newNode = new ListNode(sum % 10);
//如果当前节点有进位,就取模后为1,没有进位就保持原值
cur.next = newNode;
cur = cur.next;
p1 = (p1 == null ? null:p1.next);
p2 = (p2 == null ? null:p2.next);
}
if(carry != 0){
ListNode newNode = new ListNode(carry);
cur.next = newNode;
cur = cur.next;
}
return reverse(ans.next);
}
public ListNode reverse(ListNode list){
if(list == null) return null;
ListNode pre = null;
ListNode cur = list;
while(cur != null){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
时间复杂度;O(n),n为 l1和 l2中链表长度最长的一个
空间复杂度: O(n),n为 l1和 l2中链表长度最长的一个
第三题
难度:中等
用双端队列处理会很方便
class Solution {
public void reorderList(ListNode head) {
Deque<ListNode> stack = new LinkedList<>();
ListNode p = head, q = head;
while(p != null && p.next != null){
q = q.next;
p = p.next.next;
}
//如果p是null, 说明是偶数个
//p不是null,是奇数个
if(p == null){
while(q != null){
stack.push(q);
q = q.next;
}
}
else {
q = q.next;
while(q != null){
stack.push(q);
q = q.next;
}
}
ListNode cur = head, nex = head.next;
while(!stack.isEmpty()){
ListNode popListNode = stack.pop();
cur.next = popListNode;
popListNode.next = nex;
cur = nex;
nex = nex.next;
}
cur.next = null;
}
}
时间复杂度;O(n)
空间复杂度: O(1)