算法刷题笔记三

207 阅读2分钟


今日AC了链表类的相关题目,在此记录

leetcode25:每k个翻转一次链表
原文链接:leetcode-cn.com/problems/re…
视频讲解链接:www.bilibili.com/video/av664…

public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode end = dummy;
        while(end.next!=null){
            //1.寻找K个链表区间内尾节点
            for(int i=0;i<k&&end!=null;i++){end = end.next;}
            if(end==null) break;//不足K个则返回
            ListNode start = pre.next;
            ListNode next = end.next;
            end.next = null;
            //2.翻转K个区间内的节点
            pre.next = reverse(start);
            start.next = next;
            pre = start;
            end = pre;
        }

        return dummy.next;
    }

    //翻转局部链表
    public ListNode reverse(ListNode head){
        ListNode pre = null;
        ListNode next = null;
        ListNode cur = head;
        while(cur!=null){
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

leetcode92:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
原文链接:leetcode-cn.com/problems/re…

 public ListNode reverseBetween(ListNode head, int m, int n) {
        if(head == null || head.next == null || n<m )
            return head;
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;    
        //1.寻找m~n区间内的首尾节点
        for(int i = 1;i < m;i++){pre = pre.next;}
        ListNode start = pre.next;
        ListNode end = start;
        for(int i=0;i<n-m;i++){end = end.next;}
        ListNode next = end.next;
        end.next = null;
        //2.翻转m~n区间内的节点
        pre.next = reverse(start);
        start.next = next;
        return dummy.next;
    }
    
    public ListNode reverse(ListNode head){
        ListNode cur = head;
        ListNode pre = null;
        ListNode next = null;
        while(cur != null){
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

leetcode23:合并k个排序链表
原文链接:leetcode-cn.com/problems/me…
视频讲解:www.bilibili.com/video/av516…
关于java PriorityQueue的用法:www.jianshu.com/p/f1fd9b82c…
思路:将k个链表的首节点都丢尽优先队列中去,在逐个poll()出最小值

    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0)
            return null;
        ListNode dummy = new ListNode(0);
        ListNode pre = dummy;
        PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>(){
           public int compare(ListNode o1,ListNode o2){return o1.val - o2.val;} 
        });
        //1.将K个链表的首节点都丢入优先队列中
        for(int i=0;i<lists.length;i++){
            if(lists[i]!=null){pq.add(lists[i]);}
        }
        //2.比较并poll出最小值
        while(pq.size()!=0){
            ListNode node = pq.poll();
            pre.next = node;
            pre = pre.next;
            if(node.next!=null){
                pq.add(node.next);
            }
        }
        return dummy.next;
    }

leetcode21:合并两个有序链表
原文链接:leetcode-cn.com/problems/me…
思路一:迭代实现

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode pre = dummy;
        while(l1 != null && l2 != null){
            if(l1.val < l2.val){
                pre.next = l1;
                l1 = l1.next;
            }else{
                pre.next = l2;
                l2 = l2.next;
            }
            pre = pre.next;
        }
        //剩余的部分
        pre.next = l1==null?l2:l1;
        return dummy.next;
    }


思路二:递归实现

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null)
            return l2;
        if (l2 == null)
            return l1;
        if (l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }

leetcode19:删除链表倒数第K个节点
原文链接:leetcode-cn.com/problems/re…
思路:快慢指针法

    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode slow = dummy;
        ListNode fast = dummy;
        //快指针先走
        for(int i=0;i<n;i++){
            fast = fast.next;
        }
        //快慢指针一起走
        while(fast.next != null){
            slow = slow.next;
            fast = fast.next;
        }
        //删除倒数第K个节点
        slow.next = slow.next.next;
        return dummy.next;
    }