剑指Offer(21)-[LinkedList]两个链表的第一个公共结点

点击查看剑指Offer全解【Java & Golang】实现

题目描述

给定两个链表,寻找两个链表的第一个公共节点。
在这里插入图片描述

思路

第一种思路,创建一个HashSet,先遍历一遍链表一,并且存储每个节点在HashSet中,接着遍历链表二,如果出现了HashSet中的节点,那么该节点就是第一个公共节点。这种方法的时间复杂度为O(n + k),空间复杂度为O(n),n是第一条链表节点数,k是第二条链表节点数。

第二种思路,两个链表中,我们可以先遍历一次得到它们的长度分别为5 和4, 也就是较长的链表与较短的链表相比多一个结点。第二次先在长的链表上走1 步,到达结点2。接下来分别从结点2 和结点4 出发同时遍历两个结点, 直到找到它们第一个相同的结点6,这就是我们想要的结果。这种做法的时间复杂度也是O(n + k),但是不需要额外的空间复杂度,为O(1)。


Java第一种思路实现
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.HashSet;
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        HashSet<ListNode> set = new HashSet<>();
        while (pHead1 != null) {
            set.add(pHead1);
            pHead1 = pHead1.next;
        }
        while (pHead2 != null) {
            if (set.contains(pHead2)) {
                return pHead2;
            }
            pHead2 = pHead2.next;
        }
        return null;
    }
}
Java第二种思路实现
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.HashSet;
public class Solution {
    public ListNode FindFirstCommonNode(ListNode head1, ListNode head2) {
        int length1 = getListLength(head1);
        int length2 = getListLength(head2);
        int step = length1 - length2;
        if (step > 0) {
            for (int i = 0; i < step; i++) {
                head1 = head1.next;
            }
        } else {
            for (int i = 0; i < -step; i++) {
                head2 = head2.next;
            }
        }
        while (head1 != null && head2 != null) {
            if (head1 == head2) {
                return head1;
            }
            head1 = head1.next;
            head2 = head2.next;
        }
        return null;
    }

    private static int getListLength(ListNode head) {
        int result = 0;
        while (head != null) {
            result++;
            head = head.next;
        }
        return result;
    }
}
Golang第一种思路实现
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    set := make(map[*ListNode]string)
    for headA != nil {
        // 使用map充当set
        set[headA] = "PRESENT"
        headA = headA.Next
    } 
    for headB != nil {
        if _, ok := set[headB]; ok{
            return headB
        }
        headB = headB.Next
    }
    return nil
}
Golang第二种思路实现
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    lenA := getLength(headA)
    lenB := getLength(headB)
    step := lenA - lenB
    if step > 0 {
        for i := 0; i < step; i++ {
            headA = headA.Next
        }
    } else {
        for i := 0; i < -step; i++ {
            headB = headB.Next
        }
    }
    for headA != nil && headB != nil {
        if headA == headB {
            return headA
        }
        headA = headA.Next
        headB = headB.Next
    }
    return nil
}
func getLength(head *ListNode) int {
    cur := head
    count := 0
    for cur != nil {
        count++
        cur = cur.Next
    }
    return count
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringError

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值