0
点赞
收藏
分享

微信扫一扫

【03/17】力扣押题推荐(相交链表、环形链表2、合并K个升序链表)

160. 相交链表 

题解:

    // 双指针遍历
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        ListNode pA = headA, pB = headB;
        // 分别遍历两个链表
        // 如果遍历完当前链表,则指针指向另一个链表的头
        // 知道两个指针相遇
        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pA;
    }

    // hash表存储
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        Set<ListNode> visited = new HashSet<ListNode>();
        ListNode temp = headA;
        // 首先遍历链表 headA,并将链表 headA 中的每个节点加入哈希集合中。
        // 然后遍历链表 headB,对于遍历到的每个节点,判断该节点是否在哈希集合中:
        while (temp != null) {
            visited.add(temp);
            temp = temp.next;
        }
        temp = headB;
        while (temp != null) {
            // 如果当前节点不在哈希集合中,则继续遍历下一个节点;
            // 如果当前节点在哈希集合中,则后面的节点都在哈希集合中,即从当前节点开始的所有节点都在两个链表的相交部分
            // 因此在链表 headB 中遍历到的第一个在哈希集合中的节点就是两个链表相交的节点,返回该节点。
            if (visited.contains(temp)) {
                return temp;
            }
            temp = temp.next;
        }
        return null;
    }

142. 环形链表 II 

题解:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) { // 快慢指针
        // 如果链表是null,或者只有一个就没有环,直接返回null
        if (head == null || head.next == null){
            return null;
        }
        ListNode i = head; // 设置慢节点
        ListNode j = head; // 设置快节点
        // 循环遍历找重合点
        while (true) {
            // 如果快指针遍历结束,证明没有环
            if (j.next == null || j.next.next == null) {
                return null;
            }
            i = i.next;      // 慢指针一次移动一位
            j = j.next.next; // 快指针一次移动两位
            if (i == j) {    // 如果快慢指针重合,证明有环
                break;
            }
        }
        // 将慢指针重新指向头结点
        i = head;
        // j指针 位置不变 ,将i指针重新 指向链表头部节点 ;i和j同时每轮向前走n步; 此时f=0,s=nb;
        // 当i指针走到f=a步时,j指针走到步s=a+nb,此时 两指针重合,并同时指向链表环入口 。
        // 重新循环,返回索引为 1 (pos = 1)的链表节点(链表环入口)
        while (i != j) {
            i = i.next;
            j = j.next;
        }
        return i;
    }

    public ListNode detectCycle(ListNode head) { // hash表
        // 如果链表是null,或者只有一个就没有环,直接返回null
        if (head == null || head.next == null) {
            return null;
        }

        Set set = new HashSet<ListNode>();
        ListNode i = head;
        // 遍历链表,遍历的值如果存在hash表中,则证明有环
        while (i != null) {
            if (set.contains(i)) {
                return i;
            } else {
                set.add(i);
            }
            i = i.next;
        }
        return null;
    }
}

23. 合并K个升序链表

 思考:虽然是困难题,但是他的暴力解法并不难想,首先把所有链表放在数组中,对数组排序再转成链表即可;

题解:

    // K指针:K 个指针分别指向 K 条链表
    // 每次 O(K) 比较 K个指针求 min, 时间复杂度:O(NK)
    public ListNode mergeKLists(ListNode[] lists) { 
        int k = lists.length;
        ListNode dummyHead = new ListNode(0);
        ListNode tail = dummyHead;
        while (true) {
            ListNode minNode = null;
            int minPointer = -1;
            for (int i = 0; i < k; i++) {
                if (lists[i] == null) {
                    continue;
                }
                if (minNode == null || lists[i].val < minNode.val) {
                    minNode = lists[i];
                    minPointer = i;
                }
            }
            if (minPointer == -1) {
                break;
            }
            tail.next = minNode;
            tail = tail.next;
            lists[minPointer] = lists[minPointer].next;
        }
        return dummyHead.next;
    }


    // 我们可以想到一种最朴素的方法
    // 用一个变量 ans 来维护以及合并的链表
    // 第 i 次循环把第 i 个链表和 ans 合并,答案保存到 ans 中。
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode ans = null;
        for (int i = 0; i < lists.length; ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }

    public ListNode mergeTwoLists(ListNode a, ListNode b) {
        if (a == null || b == null) {
            return a != null ? a : b;
        }
        ListNode head = new ListNode(0);
        ListNode tail = head, aPtr = a, bPtr = b;
        while (aPtr != null && bPtr != null) {
            if (aPtr.val < bPtr.val) {
                tail.next = aPtr;
                aPtr = aPtr.next;
            } else {
                tail.next = bPtr;
                bPtr = bPtr.next;
            }
            tail = tail.next;
        }
        tail.next = (aPtr != null ? aPtr : bPtr);
        return head.next;
    }
举报

相关推荐

0 条评论