剑指Offer面试题37两个链表的第一个公共结点,面试题38数字在排序数组中出现的次数

面试题37:两个链表的第一个公共结点

输入两个单向链表,输出公共节点。注意了,两个单链表如果有公共节点,形状肯定是Y型的,因为每个结点都只有一个next结点,这个公共节点之后不会有分支了。
思路:假如链表长度分别为m和n,采用固定一个链表的第一个结点,遍历另一个链表的方法的复杂度为O(m*n),有点大了,所以换个思路,既然公共节点之后的结点都是共有的,两个链表的长度差别只在公共节点之前,所以可以先得出两个链表的长度之差d,较长的链表先走d步,然后再同时遍历两个链表,直到公共节点即可。
Java实现如下:

class ListNode{
    int data;
    ListNode next;
    public ListNode(int data) {
        this.data = data;
        this.next = null;
    }
}
public class FindFirstCommonNode {

    // 核心
    static ListNode findFirstCommonNode(ListNode list1, ListNode list2){
        int len1 = getLen(list1);
        int len2 = getLen(list2);
        int diff = 0;
        ListNode longList = null;
        ListNode shortList = null;
        if(len1 != 0 && len2 != 0){
            if(len1 > len2){
                diff = len1 - len2;
                longList = list1;
                shortList = list2;
            }else{
                diff = len2 - len1;
                longList = list2;
                shortList = list1;
            }
            for(int i = diff; i > 0;i--){
                longList = longList.next;
            }
            while(longList != null && shortList != null && longList != shortList){
                longList = longList.next;
                shortList = shortList.next;
            }
        }
        return longList;
    }

    // 求链表长度
    static int getLen(ListNode list){
        int len = 0;
        while(list != null){
            len++;
            list = list.next;
        }
        return len;
    }

    // main
    public static void main(String[] args) {
        ListNode a1 = new ListNode(1);
        ListNode a2 = new ListNode(2);
        ListNode a3 = new ListNode(3);
        ListNode a4 = new ListNode(4);
        ListNode b1 = new ListNode(1);
        ListNode b2 = new ListNode(2);
        a1.next = a2;
        a2.next = a3;
        a3.next = a4;
        b1.next = b2;
        b2.next = a3;
        System.out.println(findFirstCommonNode(a1, b1).data);
    }
}

面试题38:数字在排序数组中出现的次数

例如输入{1,2,3,3,3,3,4,5}和3,由于3出现了4次,输出4。
思路:顺序查找复杂度为O(n),我们有O(logn)的方法,就是用二分查找,找到该数字第一次出现和最后一次出现的位置即可,详见代码。
Java实现如下:

public class GetNumberOfK {

    // 二分法找第一个出现的k
    static int getFirstK(int[] arr, int k, int start, int end){
        if(start > end)
            return -1;
        int mid = (start + end) / 2;
        if(arr[mid] == k){
            if((mid > 0 && arr[mid-1] != k) || mid == 0)
                return mid;
            else
                end = mid - 1;
        }else if(arr[mid] > k)
            end = mid - 1;
        else
            start = mid + 1;
        return getFirstK(arr, k, start, end);
    }
    // 二分法找最后一个k
    static int getLastK(int[] arr, int k, int start, int end){
        if(start > end)
            return -1;
        int mid = (start + end) / 2;
        if(arr[mid] == k){
            if((mid < arr.length-1 && arr[mid+1] != k) || mid == arr.length-1)
                return mid;
            else
                start = mid + 1;
        }else if(arr[mid] < k)
            start = mid + 1;
        else
            end = mid - 1;
        return getLastK(arr, k, start, end);
    }

    // 计算个数
    static int getNumberOfK(int[] arr, int k){
        int number = 0;
        if(arr != null && arr.length > 0){
            int first = getFirstK(arr, k, 0, arr.length-1);
            int last = getLastK(arr, k, 0, arr.length-1);
            if(first >= 0 && last >= 0)
                number = last - first + 1;
        }
        return number;
    }

    public static void main(String[] args) {
        int[] arr = {1,2,3,3,3,3,4,5};
        int k = 3;
        System.out.println(getNumberOfK(arr, k));
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值