直通BAT算法面试——链表

题一:链表分化

/**
 * 题干:
 * 对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保证两类结点内部的位置关系不变。
 * 给定一个链表的头结点head,同时给定阈值val,请返回一个链表,使小于等于它的结点在前,大于等于它的在后,保证结点值不重复。
 * 测试样例:
 * {1,4,2,5},3
 * {1,2,4,5}
 * 
 * 解析:这是一个经典的荷兰过期问题,只是在这里要求在链表中完成;通过维护三个链表来完成,具体如下
 * 小于链表、等于链表、大于链表
 * 在维护的时候需要通过指针记录小于链表的尾部,需要通过指针记录等于链表的头部和尾部,需要通过指针记录大于链表的头部。
 * 最后就可以通过以上的四个指针将三个链表连在一起。
 * 
 *
 */

    class Solution{
        public  void solve(){
//          代码略
        }


    }

题二:打印两个升序链表的公共值

/**
 * 题干:
 * 现有两个升序链表,且链表中均无重复元素。请设计一个高效的算法,打印两个链表的公共值部分。
 * 给定两个链表的头指针headA和headB,请返回一个vector,元素为两个链表的公共部分。请保证返回数组的升序。两个链表的元素个数均小于等于500。保证一定有公共值
 * 测试样例:
 * {1,2,3,4,5,6,7},{2,4,6,8,10}
 * 返回:[2.4.6]
 * 
 * 解析:因为链表是有序的所以很简单,假设链表A,B。
 * 首先从链头开始比较两个链表,如果A 的当前元素等于B的当前元素,那就打印他们的当前元素,并且A、B同时指向他们的下一个元素,
 * 如果A、B的当前元素关系不是等于,那么就将较小的一方指针向前指一位,一直到找到相等的或者他们的大小关系反过来,循环此操作直到其中一个链表走完
 * 
 * 
 *
 */
class Solution{
        public  int[] solve(ListNode headA, ListNode headB) {
             // write code here
            if (headA == null || headB == null) {
                return null;
            }
            List<Integer> list = new ArrayList<>();
            while (headA != null && headB != null) {
                if (headA.val > headB.val) {
                    headB = headB.next;
                } else if (headA.val < headB.val) {
                    headA = headA.next;
                } else {
                    list.add(headA.val);
                    headA = headA.next;
                    headB = headB.next;
                }
            }
            int[] result = new int[list.size()];
            int i = 0;
            for (int j = 0; j < list.size(); j++) {
                result[j] = list.get(j);
            }
            return result;
        }


    }

    public class ListNode {
        int val;
        ListNode next = null;

        ListNode(int val) {
            this.val = val;
        }
    }

题四:
如何证明一个链表里面有环,并且返回第一个入环的节点。可以利用快慢指针来解决。
用一个快慢指针,快指针每次走两个节点,慢指针每次走一个节点,如果快慢指针能够相遇那么就代表存在环,接下来将慢指针指向头结点。重新开始往前走还是每次走一步,快指针也是同时开始往前走,但是这次一次走一个节点,他们下一次相遇的地方就是入环的第一个节点。

如果不存在环,那么在第一次快慢指针走的时候肯定是快指针走到null值他们也没有相遇。

具体证明如下:

题五:
证明两个单链表是否相交,如果相交请返回他们相交的第一个节点。

分析对于单链表如果他们相交那么相交节点以后的节点肯定 都是两个链表的共同节点。而且对于有环节点和无环节点还需分不同情况讨论。
即:1.2.3三种状况
这里写图片描述

对于途中1.2他们都是属于一种情况就是在入环节点以前就相交。

所以这道题的关键就在于讨论是否存在环;
(1)如果不存在环,直接先遍历一遍两个节点,得出两个节点长度的差值,然后较长的节点再从头结点开始遍历差值个节点(剩下未遍历部分的节点数一样),然后两个链表同时向下遍历,如果在尾节点之前他们存在相等的节点那么存在相交。反之。
(2)如果不存在环,先分别找出入环节点(如果入环节点一样那么一定是情况1)然后再分别遍历两节点,一直遍历到两节点的入环节点统计出这段的长度。然后再去执行(1)找出在他们入环之前的相交节点。

如果存在环而且经过(2)以后仍然没有搜索到相交的节点那么只有情况3能满足了,要满足情况三,就选取其中一个入环节点向下遍历,而且一定能够遍历到另一个入环节点。如果能则他们两个入环节点中的任意一个都是他们的首次相交节点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值