首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何在Java中实现求未排序数组中位数的随机O(n)算法?

在Java中实现求未排序数组中位数的随机O(n)算法,可以采用快速选择算法。

快速选择算法的基本思想是利用快速排序中的划分操作,每次选择一个基准元素将数组分成两部分,然后根据基准元素的位置,判断中位数所在的子数组是在基准元素的左侧还是右侧,从而减小问题规模。

具体实现步骤如下:

  1. 定义一个辅助方法partition(),用于进行划分操作。选择数组中的一个随机元素作为基准元素,将数组分成两部分,一部分小于基准元素,另一部分大于基准元素,同时返回基准元素的位置。
  2. 在主方法中,调用partition()方法,得到基准元素的位置。将中位数所在的子数组与基准元素的位置进行比较。
  3. 若中位数所在的子数组在基准元素的左侧,递归调用partition()方法,缩小问题规模为左侧子数组。
  4. 若中位数所在的子数组在基准元素的右侧,递归调用partition()方法,缩小问题规模为右侧子数组。
  5. 当基准元素的位置等于数组长度的一半时,即找到了中位数。

以下是Java代码示例:

代码语言:txt
复制
import java.util.Random;

public class MedianOfArray {
    public static void main(String[] args) {
        int[] nums = {5, 1, 9, 3, 7, 2};
        int median = findMedian(nums);
        System.out.println("Median: " + median);
    }
    
    public static int findMedian(int[] nums) {
        return quickSelect(nums, 0, nums.length - 1, nums.length / 2);
    }
    
    public static int quickSelect(int[] nums, int left, int right, int k) {
        if (left == right) {
            return nums[left];
        }
        
        Random random = new Random();
        int pivotIndex = left + random.nextInt(right - left);
        pivotIndex = partition(nums, left, right, pivotIndex);
        
        if (k == pivotIndex) {
            return nums[k];
        } else if (k < pivotIndex) {
            return quickSelect(nums, left, pivotIndex - 1, k);
        } else {
            return quickSelect(nums, pivotIndex + 1, right, k);
        }
    }
    
    public static int partition(int[] nums, int left, int right, int pivotIndex) {
        int pivotValue = nums[pivotIndex];
        swap(nums, pivotIndex, right);
        int storeIndex = left;
        
        for (int i = left; i < right; i++) {
            if (nums[i] < pivotValue) {
                swap(nums, i, storeIndex);
                storeIndex++;
            }
        }
        
        swap(nums, storeIndex, right);
        return storeIndex;
    }
    
    public static void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

该算法的时间复杂度为O(n),其中n为数组的长度。对于未排序的数组,可以通过快速选择算法快速求得中位数。

腾讯云相关产品推荐:云服务器(https://cloud.tencent.com/product/cvm),腾讯云云服务器(Cloud Virtual Machine,CVM)是一种可在云端进行弹性扩展的计算服务,提供了丰富的配置选项和灵活的弹性伸缩能力,适用于各类应用场景和业务需求。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

  • Leetcode 295. Find Median from Data Stream

    在一个有序数组中找中位数,但需要支持再数组中添加新的元素。本来是有序里的,可以很轻易就查到中位数,但如果添加新数字后,不一定有序。如果先对数组排序,那代价就比较大了,每次排序时间复杂度O(n*log(n)),看discuss发现了一种很巧妙的解法,可以把添加数据的时间复杂度降低到O(log(n)) ,查询中位数O(1)。   这里我们需要用到优先队列,java里有现场的优先队列。准备两个优先队列,large里存比中位数大的数,small里存比中位数小的数。加入现在有n个数,large里存最大的n/2个数,很容易理解。但small里怎么存最小的n/2个数? 这里有个很巧妙的地方,把数组里数取负存到small里,small优先队列里其实存的是数组中取负后最大的n/2个数,不就是原数组中最小的n/2个数吗?需要特别考虑到n位奇数时,large里存了n/2+1个数,small里存了n/2个数(其实多余的一个也存small里)。算中位数的时候,如果n为奇数,直接从large里去第一优先级的就好了,如果n是偶数,从large和small里各取一个求平均,注意small里取出的数要取负变换之后才能用。   代码如下,

    01

    算法导论第九章中位数和顺序统计量(选择问题)

    本章如果要归结成一个问题的话,可以归结为选择问题,比如要从一堆数中选择最大的数,或最小的数,或第几小/大的数等, 这样的问题看似很简单,似乎没有什么可研究的必要,因为我们已经知道了排序算法,运用排序+索引的方式不就轻松搞定了?但细想,排序所带来的时间复杂度是不是让这个问题无形之中变得糟糕。那算法研究不就是要尽可能避免一个问题高复杂度地解决,让那些不敢肯定有无最优解的问题变得不再怀疑,这也是算法研究者所追求的一种极致哲学。既然排序让这个问题解决的性能无法确定,那我们就抛开排序,独立研究问题本身,看有没有确

    07
    领券