- 浏览: 787479 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
萨琳娜啊:
Java读源码之Netty深入剖析网盘地址:https://p ...
Netty源码学习-FileRegion -
飞天奔月:
写得有趣 ^_^
那一年你定义了一个接口 -
GoldRoger:
第二个方法很好
java-判断一个自然数是否是某个数的平方。当然不能使用开方运算 -
bylijinnan:
<script>alert("close ...
自己动手实现Java Validation -
paul920531:
39行有个bug:"int j=new Random ...
java-蓄水池抽样-要求从N个元素中随机的抽取k个元素,其中N无法确定
网上找了一下这道题的解答,但都是提供思路,没有提供具体实现。其中使用大小堆这个思路看似简单,但实现起来要考虑很多。
以下分别用排序数组和大小堆来实现。
使用大小堆:
使用排序数组:
I'm wrong, it's correct, two inner class you mean.
以下分别用排序数组和大小堆来实现。
使用大小堆:
import java.util.Arrays; public class MedianInHeap { /** * 题目:设计方便提取中数的数据结构 * 设计一个数据结构,其中包含两个函数,1.插入一个数字,2.获得中数。并估计时间复杂度。 * 1. 使用排序数组存储。 * 插入数字时,在O(logn)时间内找到要插入的位置,在O(n)时间里移动元素并将新数字插入到合适的位置。 * 获得中数时,在O(1)复杂度内找到中数。 * 2. 使用大根堆和小根堆存储。 * 使用大根堆存储较小的一半数字,使用小根堆存储较大的一半数字。 * 插入数字时,在O(logn)时间内将该数字插入到对应的堆当中,并适当移动根节点以保持两个堆数字相等(或相差1)。 * 获取中数时,在O(1)时间内找到中数。根据中数的定义,有如下规则:如果两个堆大小相等,则分别取两个堆的根,相加并除以2. * 如果两个堆大小不等(相差1),取元素个数多的那个堆的根,即为中数。 * 3.使用二叉查找树--how? */ private MaxHeap maxHeap; private MinHeap minHeap; public static void main(String[] args) { MedianInHeap n = new MedianInHeap(); int[] data={7,9,5,3,1}; for(int each:data){ n.add(each); System.out.println("median:"+n.median()); System.out.println("==============="); } } public MedianInHeap(){ maxHeap=new MaxHeap(); minHeap=new MinHeap(); } /* * add an element into 'MedianInHeap'. * However,you need some skill. * Consider [3,5,7,9].The data size is even.Median is (5+7)/2=6. * How do we get '5' and '7'? * Of course we get them from the roots of 'maxHeap' and 'minHeap'.That is fastest. * The problem is ,which is the root of 'maxHeap'?That is, * maxHeap: 7 minHeap: 5 # or maxHeap: 5 minHeap: 7 * / / # / / * 3 9 # 3 9 * The answer is:'5' is the root of 'maxHeap'. * We use 'maxHeap' to store the smaller part of the data;'minHeap' the bigger. * You are gonna find it yourself. * So,add '1' into 'maxHeap';'6'(or '10') into 'minHeap'. */ public void add(int item) { int sizeMax = maxHeap.size; int sizeMin = minHeap.size; int rootMax = maxHeap.root(); int rootMin = minHeap.root(); if (sizeMax == 0) { maxHeap.insert(item); } else if (sizeMin == 0) { minHeap.insert(item); } else { if(sizeMax==1&&sizeMin==1&&rootMax>rootMin){//swap to make 'rootMax'<'rootMin' int tmp=maxHeap.data[0]; maxHeap.data[0]=minHeap.data[0]; minHeap.data[0]=tmp; } if (item < rootMax) {//insert into 'maxHeap' maxHeap.insert(item); if (maxHeap.size - minHeap.size > 1) { int immigrant = maxHeap.root(); minHeap.insert(immigrant); maxHeap.deleteRoot(); } } else{//insert into 'minHeap' minHeap.insert(item); if(minHeap.size-maxHeap.size>1){ int immigrant=minHeap.root(); maxHeap.insert(immigrant); minHeap.deleteRoot(); } } } System.out.print("max heap:"); maxHeap.print(); System.out.print("min heap:"); minHeap.print(); //after inserting,size is changed.So update it. sizeMax=maxHeap.size; sizeMin=minHeap.size; int[] allData=new int[sizeMax+sizeMin]; System.arraycopy(maxHeap.data, 0, allData, 0, sizeMax);//maxHeap.data,not maxHeap,or it will cause "java.lang.ArrayStoreException" System.arraycopy(minHeap.data, 0, allData, sizeMax, sizeMin); Arrays.sort(allData); System.out.println(Arrays.toString(allData)); } public double median() { int sizeMax = maxHeap.size; int sizeMin = minHeap.size; int rootMax = maxHeap.root(); int rootMin = minHeap.root(); if(sizeMax==sizeMin){ return (rootMax+rootMin)/2.0; }else{ return sizeMax>sizeMin?rootMax:rootMin; } } class MinHeap { int[] data;//maybe we could use ArrayList. int size = 0; MinHeap() { this(10); } MinHeap(int capacity) { data = new int[capacity]; } void print(){ for(int i=0;i<size;i++){ System.out.print(data[i]+" "); } System.out.println(); } int root() { return data[0]; } void deleteRoot(){ if(size>1){ data[0]=data[size-1]; reheapFromTop(0,size-2); size--; } } void insert(int item) { if (size == 0) { data[0] = item; size++; return; } if (size == data.length) { data = expandHeap(data); } data[size]=item; reheapFromBottom(0,size); size++; } //we use 'int[]' to store heap's data.When you add an element in the end,you should 'reheapFreomBottom'. void reheapFromBottom(int begin,int end) { int orphan=data[end]; boolean done = false; int curIndex=end; int rootIndex = getParent(curIndex); while (!done && rootIndex >= 0) { if (orphan < data[rootIndex]) { data[curIndex] = data[rootIndex]; curIndex = rootIndex; rootIndex = getParent(curIndex); } else { done = true; } } data[curIndex] = orphan; } //when you delete the heap's root,you should 'reheapFromTop'. void reheapFromTop(int begin,int end) { int orphan=data[begin]; boolean done=false; int rootIndex=begin; while(!done&&rootIndex<=end){ int leftIndex=rootIndex*2+1; if(leftIndex>end)break; int smallIndex=leftIndex; int rightIndex=leftIndex+1; if(rightIndex<=end&&data[rightIndex]<data[smallIndex]){ smallIndex=rightIndex; } if(data[smallIndex]<orphan){ data[rootIndex]=data[smallIndex]; rootIndex=smallIndex; }else{ done=true; } } data[rootIndex]=orphan; } } class MaxHeap { int[] data;//maybe we could use ArrayList. int size = 0; MaxHeap() { this(10); } MaxHeap(int capacity) { data = new int[capacity]; } int root() { return data[0]; } void print(){ for(int i=0;i<size;i++){ System.out.print(data[i]+" "); } System.out.println(); } void deleteRoot(){ if(size>1){ data[0]=data[size-1]; reheapFromTop(0,size-2); size--; } } void insert(int item) { if (size == 0) { data[0] = item; size++; return; } if (size == data.length) { data = expandHeap(data); } data[size]=item; reheapFromBottom(0,size); size++; } void reheapFromBottom(int begin,int end) { int orphan=data[end]; boolean done = false; int curIndex=end; int rootIndex = getParent(curIndex); while (!done && rootIndex >= 0) { if (orphan > data[rootIndex]) { data[curIndex] = data[rootIndex]; curIndex = rootIndex; rootIndex = getParent(curIndex); } else { done = true; } } data[curIndex] = orphan; } void reheapFromTop(int begin,int end) { int orphan=data[begin]; boolean done=false; int rootIndex=begin; while(!done&&rootIndex<=end){ int leftIndex=rootIndex*2+1; if(leftIndex>end)break; int largerIndex=leftIndex; int rightIndex=leftIndex+1; if(rightIndex<=end&&data[rightIndex]>data[largerIndex]){ largerIndex=rightIndex; } if(data[largerIndex]>orphan){ data[rootIndex]=data[largerIndex]; rootIndex=largerIndex; }else{ done=true; } } data[rootIndex]=orphan; } } //get root's index from a child's index int getParent(int curIndex) { return (curIndex % 2 == 0) ? (curIndex / 2 - 1) : (curIndex / 2); } //int[n]-->int[2*n] int[] expandHeap(int[] data) { int size = data.length; int[] newArray = new int[data.length * 2]; for (int i = 0; i < size; i++) { newArray[i] = data[i]; } return newArray; } }
使用排序数组:
public class MedianInSortedArray { /** * 题目:设计方便提取中数的数据结构 * 设计一个数据结构,其中包含两个函数,1.插入一个数字,2.获得中数。并估计时间复杂度。 * 1. 使用排序数组存储。 * 插入数字时,在O(logn)时间内找到要插入的位置,在O(n)时间里移动元素并将新数字插入到合适的位置。 * 获得中数时,在O(1)复杂度内找到中数。 * 2. 使用大根堆和小根堆存储。 * 使用大根堆存储较小的一半数字,使用小根堆存储较大的一半数字。 * 插入数字时,在O(logn)时间内将该数字插入到对应的堆当中,并适当移动根节点以保持两个堆数字相等(或相差1)。 * 获取中数时,在O(1)时间内找到中数。根据中数的定义,有如下规则:如果两个堆大小相等,则分别取两个堆的根,相加并除以2. * 如果两个堆大小不等(相差1),取元素个数多的那个堆的根,即为中数。 * 3.使用二叉查找树--how? */ public static void main(String[] args) { //1.Median implemented by sorted array MedianInArray m=new MedianInArray(); for(int i=0;i<12;i++){ m.insert(i); m.print(); System.out.println(" median is "+m.getMedian()); } } private static class MedianInArray{ int[] data; int size=0;//record the number of elements MedianInArray(){ this(10); } MedianInArray(int capacity){ data=new int[capacity]; } //like "Insertion Sort" void insert(int item){ if(size==0){ data[size]=item; size++; }else{ if(size+1>data.length){ expandArray(); } int index=size-1; while(index>=0&&data[index]>item){//move backward for insertion data[index+1]=data[index]; index--; } data[index+1]=item; size++; } } double getMedian(){ int mid=size/2; if((size &(0x01))==1){ return data[mid]; }else{ return (data[mid]+data[mid-1])/2.0; } } void expandArray(){ int capacity=data.length*2; int[] newArray=new int[capacity]; for(int i=0;i<size;i++){//"System.arraycopy" also works newArray[i]=data[i]; } data=newArray; } void print(){ for(int i=0;i<size;i++){ System.out.print(data[i]+" "); } } } }
评论
3 楼
neyshule
2012-06-14
neyshule 写道
第一种解法扩号不对称啊,是内部类吗?
I'm wrong, it's correct, two inner class you mean.
2 楼
neyshule
2012-06-14
第一种解法扩号不对称啊,是内部类吗?
1 楼
neyshule
2012-06-13
严重支持!
发表评论
-
二维数组(矩阵)对角线输出
2014-04-28 17:55 4677/** 二维数组 对角线输出 两个方向 例如对于数 ... -
bitmap求哈密顿距离-给定N(1<=N<=100000)个五维的点A(x1,x2,x3,x4,x5),求两个点X(x1,x2,x3,x4,x5)和Y(
2012-12-27 21:12 2954import java.util.Random; / ... -
百度笔试题:一个已经排序好的很大的数组,现在给它划分成m段,每段长度不定,段长最长为k,然后段内打乱顺序,请设计一个算法对其进行重新排序
2012-12-21 18:17 4102import java.util.Arrays; ... -
有一个数组,每次从中间随机取一个,然后放回去,当所有的元素都被取过,返回总共的取的次数。写一个函数实现。复杂度是什么。
2012-12-07 14:32 3604import java.util.Random; i ... -
单调队列-用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值
2012-11-11 22:32 2357import java.util.LinkedList; ... -
据说是2012年10月人人网校招的一道笔试题-给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 将重物放到天平左侧,问在两边如何添加砝码
2012-10-28 23:41 1971public class ScalesBalance { ... -
java-并查集(Disjoint-set)-将多个集合合并成没有交集的集合
2012-04-28 00:02 8418import java.util.ArrayList; ... -
java-拷贝特殊链表:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?
2012-04-20 10:04 2981public class CopySpecialLinke ... -
java-写一函数f(a,b),它带有两个字符串参数并返回一串字符,该字符串只包含在两个串中都有的并按照在a中的顺序。
2012-04-17 19:50 3484public class CommonSubSeque ... -
java-同步访问一个数组Integer[10],生产者不断地往数组放入整数1000,数组满时等待;消费者不断地将数组里面的数置零,数组空时等待
2012-04-14 15:39 2321public class PC { /** ... -
java-两整数相除,求循环节
2012-04-14 13:52 4651import java.util.ArrayList; ... -
java-颠倒一个句子中的词的顺序。比如: I am a student颠倒后变成:student a am I
2012-04-14 10:27 3990public class ReverseWords { ... -
java-谷歌面试题-给定一个排序数组,如何构造一个二叉排序树
2012-04-12 11:10 4382import java.util.LinkedList; ... -
java-腾讯暑期实习生-输入一个数组A[1,2,...n],求输入B,使得数组B中的第i个数字B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]
2012-04-08 23:10 3791这道题的具体思路请参看 何海涛的微博:http://weibo ... -
java-给定两个已排序序列,找出共同的元素。
2012-04-06 13:09 2862import java.util.ArrayList; ... -
java-谷歌面试题-给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数
2012-03-31 12:16 5022public class SearchInShifte ... -
java-13个坏人和13个好人站成一圈,数到7就从圈里面踢出一个来,要求把所有坏人都给踢出来,所有好人都留在圈里。请找出初始时坏人站的位置。
2012-03-28 22:13 1547import java.util.ArrayList; ... -
java-给定字符串,删除开始和结尾处的空格,并将中间的多个连续的空格合并成一个。
2012-03-26 10:59 7666public class DeleteExtraSpa ... -
java实现两个大数相加,可能存在溢出。
2012-03-25 11:08 6706import java.math.BigInteger; ... -
给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数
2012-03-21 22:15 3743import java.util.ArrayList; ...
相关推荐
#### 2.9 Java 中有哪些数据类型? Java 中的数据类型分为两大类: - **原始类型**:包括 int、long、float、double、char、boolean、byte、short。 - **引用类型**:包括类、数组、接口。 #### 2.10 如何解决 ...
在学习大数据的过程中,还需要掌握数据处理的基本概念,如ETL(提取、转换、加载)、数据仓库和数据湖的概念,以及数据建模和清洗的技巧。此外,了解云计算平台,如Amazon Web Services (AWS)的EMR(Elastic ...
### Google综合问题解析 #### 1. 字符串处理 - **问题描述**:给定一个字符串,返回一个由单词组成的列表。单词被定义为由一个或多个空格分隔,或被引号包围的字符序列。...- **知识点**:数据结构设计,矩阵操作。
校招java笔试题谷歌面试大学 翻译: 它是什么? 这是我从 Web 开发人员(自学,没有 CS 学位)到 Google 软件工程师的为期数月的学习计划。 这份长长的清单是从Google 的指导说明中提取和扩展的,因此这些是您需要...
初级java笔试题谷歌面试大学 翻译: 它是什么? 这是我从 Web 开发人员(自学,没有 CS 学位)到 Google 软件工程师的为期数月的学习计划。 这份长长的清单是从Google 的指导说明中提取和扩展的,因此这些是您需要...
以上知识点涵盖了文件中提及的面试题内容,能够为准备互联网公司Java工程师面试的候选人提供参考和准备的方向。在实际面试准备中,除了理解上述知识点之外,还需要结合实际项目经验,进行深入学习和实践。
- **《算法第四版》**:本书系统地介绍了常见的数据结构与算法,特别强调了排序和查找算法。 - 排序算法(冒泡、选择、插入、快速、堆排序等) - 查找算法(二分查找、哈希表) #### 面试题解 - **《剑指Offer第...
排序可以通过自定义Partitioner和Comparator来实现,而选取TopN则可以通过维护一个最小堆等数据结构来完成。 - **MapReduce求两个人的共同好友算法** 这类社交网络中的问题可以转化为查找两个用户之间的交集问题...
- `java.util.concurrent`包提供了许多线程安全的数据结构和实用工具类,如`ExecutorService`、`Future`、`Semaphore`等。 **38. volatile关键字** - 用于标记一个变量的值可能被其他线程改变,保证变量的可见性和...