第一关(白银):链表高频面试算法题

文章介绍了四种不同的方法来找到两个链表的第一个公共节点:1)使用哈希集,遍历一个链表后检查第二个链表的节点;2)利用栈的特性,将两个链表入栈后对比;3)拼接两个链表并同时遍历;4)计算链表长度差异后双指针同步遍历。这些方法旨在解决数据结构问题,优化链表操作效率。
摘要由CSDN通过智能技术生成

1输入两个链表,找出它们的第一个公共节点

 1.1使用集合,运用Hash特性进行检测

public ListNode findFirstCommonNodeBySet(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;
}

运用contains()方法,遍历链表A之后和链表B进行对比

1.2使用栈

import java.util.Stack;
    public ListNode findFirstCommonNodeByStack(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 preNode=null;
      while(stackB.size()>0 && stackA.size()>0){
          if(stackA.peek()==stackB.peek()){
            preNode=stackA.pop();
             stackB.pop();
          }else{
              break;
          }
      }
        return preNode;
    }

基于栈先进后出的特性,将两个链表分别入栈,然后进行出栈,最后一组相同的正是两个链表的公共节点

1.3拼接两个字符串

public ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
         if(pHead1==null || pHead2==null){
             return null;
         }
        ListNode p1=pHead1;
        ListNode p2=pHead2;
        while(p1!=p2){
            p1=p1.next;
            p2=p2.next;
            if(p1!=p2){
            //一个链表访问完了就跳到另外一个链表继续访问
                if(p1==null){
                    p1=pHead2;
                }
                if(p2==null){
                    p2=pHead1;
                }
            }
        }
        return p1;
    }

试想一下,当两条线相交成一条线的时候,那么可以说明,这两条线在交点右侧的部分是完全相同的。这句话看起来是废话,但是运用在编程当中,可以将两个链表相互收尾相连,形成两条等长的链表,这样可以对两条链表进行同时遍历。当有相同的节点时,就是原本两条链表的交点。

在上面这段代码中,因为想要节省空间,于是增加了判断,使用指针指向链表,当链表p1遍历完了,指针立马指向链表p2,如同两个链表连在一起一样。但是这就会遇到一种情况,当两个链表没有交点时且他们的指针同时指向null的时候,这个时候本来应该已经比较结束了,但是指针又会重新连接一遍链表,造成死循环。因此对代码进行优化加入p1!= p2的判断

1.4差和双指针

public ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
     if(pHead1==null || pHead2==null){
             return null;
         }
        ListNode current1=pHead1;
        ListNode current2=pHead2;
        int l1=0,l2=0;
        //分别统计两个链表的长度
        while(current1!=null){
            current1=current1.next;
            l1++;
        }
        
         while(current2!=null){
            current2=current2.next;
            l2++;
        }
        current1=pHead1;
        current2=pHead2;
        int sub=l1>l2?l1-l2:l2-l1;
        //长的先走sub步
       if(l1>l2){
           int a=0;
           while(a<sub){
            current1=current1.next;
            a++;
        }   
       }
      
       if(l1<l2){
           int a=0;
           while(a<sub){
            current2=current2.next;
            a++;
        }   
       }
        //同时遍历两个链表
       while(current2!=current1){
          current2=current2.next;
          current1=current1.next;
       } 
        
        return current1;
    }

可以知道的是,当两条链表可以通过某个节点后汇聚成一条链表,并且两条链表的长度并不一样长的时候,这两条链表的相交点一定不在短链表比长链表短的那一部分上,因此可以先去掉长链表开始时多的那一部分,从两个链表长度相等时开始比较

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值