数据流中的中位数,字符流中第一个不重复的字符,连续子数组的最大和

题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用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;
	}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值