zoukankan      html  css  js  c++  java
  • 4. 寻找两个正序数组的中位数(利用二分查找找出两个有序数组第k小的元素)

    4. 寻找两个正序数组的中位数

    package 数组;
    
    public class 找两个正序数组的中位数找第k小的数 {
        public static void main(String[] args) {
    //        int[] a = {1, 3, 4, 9};//长度为4
    //        int[] b = {1, 2, 3, 4, 5, 6, 7, 8, 9};//长度为9
    //        int[] a = {1, 2};//长度为2
    //        int[] b = {3, 4};//长度为1
            int[] a = {1};//长度为2
            int[] b = {2, 3, 4, 5, 6};//长度为1
            找两个正序数组的中位数找第k小的数 o = new 找两个正序数组的中位数找第k小的数();
    
            System.out.println(o.findMedianSortedArrays(a, b));
        }
    
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int total = nums1.length + nums2.length;
            if (total % 2 == 1) {
                return getKMinNum(nums1, nums2, (total + 1) / 2);
            } else {
                int k1 = getKMinNum(nums1, nums2, total / 2);
                int k2 = getKMinNum(nums1, nums2, total / 2 + 1);
                return (k1 + k2) / 2.0;
    //            return k2;
            }
        }
        
        /* 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
         * 这里的 "/" 表示整除
         * nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个
         * nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个
         * 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
         * 这样 pivot 本身最大也只能是第 k-1 小的元素
         * 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
         * 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
         * 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
         */
        public int getKMinNum(int[] a, int[] b, int k) {
            // 由于是求第k小的数,因此index不能直接去k/2,这样a和b用的数组的两段长度加和就是8个了,应该k/2-1
            // 2
            int indexA = 0;
            int indexB = 0;
            int newIndexA = 0;
            int newIndexB = 0;
            while (true) {
                //边界条件
                // 当数组a的元素全部被排除掉之后,第k小的元素直接在数组b中取
                if (newIndexA == a.length) {
                    return b[newIndexB + k - 1];
                }
                if (newIndexB == b.length) {
                    return a[newIndexA + k - 1];
                }
                // 两个数组都有剩余元素,去第一小的元素直接比较两个剩余数组的头元素即可
                if (k == 1) {
                    return Math.min(a[newIndexA], b[newIndexB]);
                }
                indexB = Math.min(newIndexB + (k / 2 - 1),b.length-1);
                indexA = Math.min(newIndexA + (k / 2 - 1),a.length-1);
                if (a[indexA] > b[indexB]) {
                    // b的前k/2个元素排除掉,第k小的数不在里面
                    // b的起始位置可以视为k/2+1
                    // 去掉排除过的元素,重新计算k的值
                    k = (k - (indexB-newIndexB)-1);
                    // b数组排除掉前k/2个元素之后,剩余数组的起始坐标
                    newIndexB = indexB + 1;
                } else {
                    k = (k - (indexA-newIndexA)-1);
                    newIndexA = indexA + 1;
                }
            }
    
        }
    
    }

    。。

  • 相关阅读:
    laravel基础课程---1、laravel安装及基础介绍(laravel如何安装)
    英语发音规则---gh
    英语影视台词---无敌破坏王2大脑互联网
    C#入门---2、C#装备知识(C#创建桌面程序的时候创建的是什么应用程序)
    android sdk linux 文本 64 位置
    使用内联中间语言
    全栈JavaScript路(八)得知 CDATASection 种类 节点
    HDU-4628 Pieces 如压力DP
    Hadoop加zookeeper构建高可靠集群
    递归嵌套列表
  • 原文地址:https://www.cnblogs.com/guoyu1/p/15615194.html
Copyright © 2011-2022 走看看