题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
解题思路
我们可以将数据排序后分为两部分,左边部分的数据总是比右边的数据小。那么,我们就可以用最大堆和最小堆来装载这些数据:
最大堆装左边的数据,取出堆顶(最大的数)的时间复杂度是O(1)
最小堆装右边的数据,同样,取出堆顶(最小的数)的时间复杂度是O(1)
从数据流中拿到一个数后,先按顺序插入堆中:如果左边的最大堆是否为空或者该数小于等于最大堆顶的数,则把它插入最大堆,否则插入最小堆。然后,我们要保证左边的最大堆的size等于右边的最小堆的size或者最大堆的size比最小堆的size大1。
要获取中位数的话,直接判断最大堆和最小堆的size,如果相等,则分别取出两个堆的堆顶除以2得到中位数,不然,就是最大堆的size要比最小堆的size大,这时直接取出最大堆的堆顶就是我们要的中位数。
public class FourtyOne {
//最小堆
private PriorityQueue<Integer> rheap=new PriorityQueue<>();
//最大堆
private PriorityQueue<Integer> lheap=new PriorityQueue<>(10,new Comparator<Integer>() {
public int compare(Integer o1,Integer o2) {
return o2-o1;
}
});
//保证lheap.size()>=rheap.size()
public void insert(Integer num) {
if(lheap.isEmpty()||num<=lheap.peek()) {
lheap.offer(num);
}else {
rheap.offer(num);
}
if(lheap.size()<rheap.size()) {
lheap.offer(rheap.peek());
rheap.poll();
}else if(lheap.size()-rheap.size()==2) {
rheap.offer(lheap.peek());
lheap.poll();
}
}
public Double getMiddle() {
if(lheap.size()>rheap.size()) {
return new Double(lheap.peek());
}else {
return new Double(lheap.peek()+rheap.peek())/2;
}
}
题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符 “go” 时,第一
个只出现一次的字符是 “g”。当从该字符流中读出前六个字符“google" 时,第一个只出现一次的字符是 “l”。
解题思路
将字符中放入map中,让字符作为key,如果有重复的话,对应的map的值加一,遍历map找到第一个先出现key的值为一,就是字符流中第一个不重复的字符
/**
* 字符流中第一个不重复的字符
* @param args
*/
public char firstAppearingOnce(char[] ch) {
HashMap<Character, Integer> map=new HashMap<>();
ArrayList<Character> list=new ArrayList<>();
for(int i=0;i<ch.length;i++) {
if(map.containsKey(ch[i])) {
map.put(ch[i], map.get(ch[i])+1);
}else {
map.put(ch[i], 1);
}
list.add(ch[i]);
}
char c='#';
for(char key:list) {
if(map.get(key)==1) {
c=key;
break;
}
}
return c;
}
题目描述
{6, -3, -2, 7, -15, 1, 2, 2},连续子数组的最大和为 8(从第 0 个开始,到第 3 个为止)。
解题思路
对于一个数组中的一个数x,若是x的左边的数加起来非负,那么加上x能使得值变大,这样我们认为x之前的数的和对整体和是有贡献的。如果前几项加起来是负数,则认为有害于总和。
我们用tmp记录当前值, 用max记录最大值,如果cur<0,则舍弃之前的数,让tmp等于当前的数字,否则,tmp =tmp+当前的数字。若tmp和大于max更新max
/**
* 连续子数组的最大和
* 总共有n(n+1)/2
* @author xhh
*
*/
public class FourtyTwo {
public int findGreatestSumOfSubArray(int[] array) {
if(array.length==0||array==null) {
return 0;
}
int tmp=array[0];
int max=array[0];
for(int i=1;i<array.length;i++) {
if(tmp>0) {
tmp=tmp+array[i];
}else {
tmp=array[i];
}
if(max<tmp) {
max=tmp;
}
}
return max;
}
}