剑指offer 36:两个链表的第一个公共节点--- Java实现

剑指offer每日一题算法题(java解法)

方便日后复习,从今天开始。

算法之行始于足下

[编程题]两个链表的第一个公共节点-- Java实现

------------------------------------------------------------------------------------------------------
题目描述
输入两个链表,找出它们的第一个公共结点。

前提:
理解什么是公共节点,公共节点的意思就是当前节点值相等,且后面的子链表值和长度一一对应相等
在这里插入图片描述

解题思路:
方法一

最直观就是暴力法,在第一链表上顺序遍历每个节点,每遍历到一个节点,就在第二个链表上顺序遍历每个节点。如果在第二个链表上有一个节点和第一个链表上的节点一样,则说明两个链表在这个节点上重合,但是这种方法的复杂度为O(m∗nm * nm∗n)(第一个链表长度为m,第二个链表的长度为n)
方法二

如果两个链表存在公共节点,那么公共节点出现在两个链表的尾部。如果我们从两个链表的尾部开始往前比较,那么最后一个相同的节点就是我们要找的节点。但是这两个链表是单向的,要实现尾节点最先比较,我们可以借助两个辅助栈。分别将两个链表的节点放入两个栈中,这样栈顶就是两个链表的尾节点,比较两个栈顶节点是否相同,如果相同,将栈顶弹出比较下一个栈顶,直到找到最后一个相同的栈顶。时间复杂度O(m + n)。

/*
public class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.Stack;
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1==null||pHead2==null) return null;
        Stack<ListNode> pStack1=new Stack<ListNode>();
        Stack<ListNode> pStack2=new Stack<ListNode>();
        while(pHead1!=null){
            pStack1.push(pHead1);
            pHead1=pHead1.next;
        }
        while(pHead2!=null){
            pStack2.push(pHead2);
            pHead2=pHead2.next;
        }
        ListNode tmp=null;
        while(!pStack1.isEmpty()&&!pStack2.isEmpty()){
            ListNode pH1=pStack1.pop();
            ListNode pH2=pStack2.pop();
            if(pH1.val==pH2.val){
                tmp=pH1;
            }else{
                break;
            }
        }
        return tmp;
    }
}

方法三

先获得两个链表的长度,然后在较长的链表上先走若干步(两链表长度之差),接着同时在两个链表上遍历,找到的第一个相同的节点就是他们的第一个公共节点。时间复杂度O(m + n)。

public ListNode FindFirstCommonNode_2(ListNode pHead1, ListNode pHead2) {
     if(pHead1 == null || pHead2 == null) {
      return null;
     } 
     int pHead1Length = getListLength(pHead1);
     int pHead2Length = getListLength(pHead2);  
     int gap = pHead1Length - pHead2Length;
     ListNode tempList1 = pHead1;
     ListNode tempList2 = pHead2;   
     if(pHead2Length > pHead1Length) {
      tempList1 = pHead2;
      tempList2 = pHead1;
      gap = pHead2Length - pHead1Length;
     }   
     for (int i = 0; i < gap; i++) {
      tempList1 = tempList1.next;
     }   
     while((tempList1 != null) && (tempList2 != null) && (tempList1.val != tempList2.val)) {
      tempList1 = tempList1.next;
      tempList2 = tempList2.next;
     }   
     return tempList1;
     } 
     public int getListLength(ListNode list) {
     int number = 0;
     while(list != null) {
      ++number;
      list = list.next;
     }
     return number;
    }

方法四

用两个指针扫描”两个链表“,最终两个指针到达 null 或者到达公共结点。

public ListNode FindFirstCommonNode_3(ListNode pHead1, ListNode pHead2) {
     if(pHead1 == null || pHead2 == null) {
      return null;
     }
     ListNode temp1 = pHead1;
     ListNode temp2 = pHead2;
     while(temp1 != temp2) {
      temp1 = (temp1 == null ? pHead2 : temp1.next); 
      temp2 = (temp2 == null ? pHead1 : temp2.next);
      System.out.println(pHead1.val);
     } 
     return temp1;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值