链表刷题

92 阅读2分钟

一、链表反转

剑指 Offer 24. 反转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
}

25. K 个一组翻转链表

思路:反转链表的衍生,也是先分组再反转链表。
设定一个分组,保存分组的前一个结点pre,分组的后一个结点next,分组第一个结点start,分组最后一个结点end,然后让分组中的链表,进行反转,如果分组大小小于k就不需要反转了。
开始图是这样的: pre ----> [ start ----> ......----> end ] ----> next ---->......
反转后:pre ----> [ end ----> ......----> start ] ----> next ---->......
而分组中的反转,就可以直接用24题的反转链表方法

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        //虚拟头结点
        ListNode dummy = new ListNode();
        dummy.next = head;
        
        //保存分组的前一个结点
        ListNode pre = dummy;
        //分组的最后一个结点
        ListNode end = dummy;
        while(end.next != null){
            //循环k次,找到最后一个
            for(int i = 0; i < k && end != null; i++) end = end.next;
            //小于k保持原有顺序
            if(end == null) break;
            
            //分组的第一个结点
            ListNode start = pre.next;
            //保存end的下一个
            ListNode next = end.next;

            //断开end和next的链接
            end.next = null;
            //反转start到end
            pre.next = reverse(start);
            //此时start和end反转了,这里的start其实在最后一个
            //重新连接
            start.next = next;
            pre = start;
            end = pre;

        }
        return dummy.next;
    }

    private ListNode reverse(ListNode head){
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode next = cur.next;
            //反转
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
}

二、合并链表

21. 合并两个有序链表

思路:递归,比较哪个小,小的那个的next指针指向,下一个指针和另外一个链表中小的那个

/**
 * 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; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        if(list1.val < list2.val){
            list1.next = mergeTwoLists(list1.next, list2);
            return list1;
        }else{
            list2.next = mergeTwoLists(list1, list2.next);
            return list2;
        }

         
    }
}