算法通关村第一关——链表白银挑战笔记

文章目录

    • 两个链表的第一个重合节点
    • 判断回文链表


两个链表的第一个重合节点

LeetCode 160.相交链表
解法一:Hash和Set(集合),此处用Set合适。
把其中一个链表的所有节点引用放入set,再从头遍历另一个链表第一次重合的地方就是答案。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    Set<ListNode> set = new HashSet<>();
    while(headA != null){
        set.add(headA);
        headA = headA.next;
    }
    while(headB != null){
        if(set.contains(headB)) return headB;
        headB = headB.next;
    }
    return null;
}

解法二:使用栈
两个链表都分别入栈,出栈的时候判断最后一个相同引用。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    Stack<ListNode> stackA = new Stack<>();
    Stack<ListNode> stackB = new Stack<>();
    while (headA != null) {
        stackA.push(headA);
        headA = headA.next;
    }
    while (headB != null) {
        stackB.push(headB);
        headB = headB.next;
    }
    ListNode cur = null;
    while (!stackA.isEmpty() && !stackB.isEmpty()) {
        if (stackA.peek() == stackB.peek()) {
            cur = stackA.pop();
            stackB.pop();
        } else break;
    }
    return cur;
}

前两种解法利用了数据结构的特点,下面两种则是将两个链表的长度设法弄成一样的,之后节点映射对比。


解法三:拼接
如图AB两个链表如果有重合部分,则可以把AB链表分成 left 和 right 部分,易知 right_a = right_b 。将AB两个链表按照AB、BA两种方式拼接得到的结果可以看到有重合部分,这样两个链表长度相等,则可以映射对比。
算法通关村第一关——链表白银挑战笔记_第1张图片
算法通关村第一关——链表白银挑战笔记_第2张图片

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null || headB==null) return null;
        ListNode node1 = headA;
        ListNode node2 = headB;
        while (node1 != node2){
            node1 = node1.next;
            node2 = node2.next;
            if(node1 == node2) break;
            // 因为两个合并链表长度一定相等,也就是说遍历完合并链表一定能得到答案。这个判断是对AB链表无交集情况的判断,防止死循环。
            if (node1!=node2) { 
                if(node1==null) node1 = headB;
                if(node2==null) node2 = headA;
            }
        }
        return node1;
    }

解法四:消余
同思路三都是让链表长度相等再遍历。这个方法就是让长的链表遍历到和短链表长度相等时比较。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if(headA==null || headB==null) return null;
    ListNode node1 = headA;
    ListNode node2 = headB;
    int l1 = 0, l2 = 0;
    while (node1!=null){
        l1++;
        node1 = node1.next;
    }
    while (node2!=null){
        l2++;
        node2 = node2.next;
    }
    int l = Math.abs(l1-l2);
    if(l1>l2){
        while (l!=0){
            headA = headA.next;
            l--;
        }
    }else {
        while (l!=0){
            headB = headB.next;
            l--;
        }
    }
    while (headA!=headB){
        headA = headA.next;
        headB = headB.next;
    }
    return headA;
}

判断回文链表

LeetCode 234.回文链表
解法一:入栈对比。

ublic boolean isPalindrome(ListNode head) {
    Stack<ListNode> stack = new Stack<>();
    ListNode cur = head;
    int l = 0;
    // 将全部元素入栈
    while (cur != null){
        stack.push(cur);
        cur = cur.next;
        l++;
    }
    // 比价一半长度即可
    l /= 2;
    while (l!=0) {
        if(head.val != stack.pop().val) return false;
        head = head.next;
        l--;
    }
    return true;
}

解法二:翻转链表。
使用快慢指针遍历(也可以遍历求长度,然后遍历到链表的中间),然后翻转链表后半部分,再与原链表对比。

public boolean isPalindrome(ListNode head) {
    ListNode slow = head;
    ListNode fast = head;
    while (fast!=null && fast.next!=null){
        fast = fast.next.next;
        slow = slow.next;
    }
    fast = reverse(slow);
    while (fast!=null){
        if(fast.val!= head.val) return false;
        fast = fast.next;
        head = head.next;
    }
    return true;
}

private ListNode reverse(ListNode head) {
    ListNode cur = head.next;
    head.next = null;
    while (cur!=null){
        ListNode curNext = cur.next;
        cur.next = head;
        head = cur;
        cur = curNext;
    }
    return head;
}

你可能感兴趣的:(算法与数据结构,算法,链表,笔记)