(剑指offer)两个单向链表,找出它们的第一个公共结点

题目:输入两个单向链表,找出它们的第一个公共结点
如:给定链表1:6–>1–>2–>4–>3–>2–>5–>2–>6
    链表2:2–>1–>8–>3–>2–>5–>2–>6


算法思路:
  首先第一次遍历两个链表,分别得到它们的长度为m和n,判断链表长度m和n的大小,第二次遍历时,先在较长的一个链表上走(m-n或n-m)步,再同时在两个链表上遍历,直到找到它们第一个相同的结点3;
  
时间复杂度为: O(m+n)


代码如下:

public class Node {
    public int value;
    public Node next;

    public Node() {}

    public Node(int value) {
        this.value = value;
    }
}
public class LinkPublicNode {

    public static void main(String[] args) {
        int[] arr_1 = { 6, 1, 2, 4, 3, 2, 5, 2, 6 };
        int[] arr_2 = { 2, 1, 8, 3, 2, 5, 2, 6 };
        Node link_1 = generateLink(arr_1);
        Node link_2 = generateLink(arr_2);
        print(link_1.next);
        print(link_2.next);
        System.out.println(findFirstSameNode(link_1, link_2).value);
    }

    /**
     * 计算两个单链表的第一个公共结点,找到返回结点,否则返回null
     * @param head_1
     * @param head_2
     * @return
     */
    public static Node findFirstSameNode(Node head_1, Node head_2) {
        if (head_1 == null || head_2 == null) {
            return null;
        }
        int lengthOfHead_1 = calculateLength(head_1);
        int lengthOfHead_2 = calculateLength(head_2);
        if (lengthOfHead_1 > lengthOfHead_2) { // 判断一下两个链表的长度,此时链表head_1较长
            for (int i = 0; i < lengthOfHead_1 - lengthOfHead_2; i++) {
                head_1 = head_1.next;
            }
            while (head_2 != null) {
                if (head_1.value == head_2.value)
                    return head_1;
                head_1 = head_1.next;
                head_2 = head_2.next;
            }
        } else { // 此时链表head_2较长
            for (int i = 0; i < lengthOfHead_2 - lengthOfHead_1; i++) {
                head_2 = head_2.next;
            }
            while (head_1 != null) {
                if (head_1.value == head_2.value)
                    return head_1;
                head_1 = head_1.next;
                head_2 = head_2.next;
            }
        }
        return null;
    }

    /**
     * 计算链表的长度
     * @param head
     * @return 返回链表的长度
     */
    public static int calculateLength(Node head) {
        Node temp = head.next;
        int len = 0;
        while (temp != null) {
            len++;
            temp = temp.next;
        }
        return len;
    }

    /**
     * 传入数组参数构造单链表
     * @param arr 数组
     * @return 构造的单链表
     */
    public static Node generateLink(int[] arr) {
        Node head = new Node(); // 链表的头结点
        Node pre = head;
        for (int i = 0; i < arr.length; i++) { // 遍历数组构建链表
            Node node = new Node(arr[i]);
            pre.next = node; // 构造链表
            pre = node;
        }
        return head;
    }

    /**
     * 打印输出链表的结点值
     * @param head 链表头结点的下一个结点
     */
    public static void print(Node head) {
        while (head != null) {
            System.out.print(head.value + " ");
            head = head.next;
        }
        System.out.println();
    }
}

结果如下:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值