48数据流中的中位数 49表达式 50两数之和

48数据流中的中位数

在这里插入图片描述
第一次没看到要求排序,还以为题目答案写错了,用排序的内置函数也正好是nlogn

import java.util.ArrayList;

public class Solution {
    ArrayList<Integer> list = new ArrayList<>();
    
    public void Insert(Integer num) {
        list.add(num);   
    }

    public Double GetMedian() {
        ArrayList<Integer> list2 = (ArrayList<Integer>)list.clone();
        list2.sort((a,b)->a-b);
        int length=list.size();

        if(length%2==1){//奇数
            return list2.get((length-1)/2).doubleValue();
        }
        else{
            return (list2.get(length/2).doubleValue()+list2.get(length/2-1).doubleValue())/2;
        }
        
    }

}

Integer转换为Double:
list2.get((length-1)/2).doubleValue();

法二,用插入排序

因为每次都是增加一个元素,不如直接维护原来的有序数组,这样每次插入的时间复杂度为O(N), GetMedian的时间复杂度为O(1),空间复杂度为O(n)

import java.util.*;

public class Solution {
    private ArrayList<Integer> list = new ArrayList<Integer>();

    public void Insert(Integer num) {
        int i=0;
        for( i=0;i<list.size();i++){
            if(list.get(i)>num) break;//找到第一个大于它的,插入
        }
        list.add(i,num);
    
    }

    public Double GetMedian() {
        int length=list.size();

        if(length%2==1){//奇数
            return list.get((length-1)/2).doubleValue();
        }
        else{
            return (list.get(length/2).doubleValue()+list.get(length/2-1).doubleValue())/2;
        }
        
    }


}

list(index i, E element)可以向指定索引插入元素,后面的自动后移

法3,优先队列

维护两个优先队列,一个最大堆存数组中最小的一半元素,一个最小堆存数组中最大的一半元素,如果是偶数就两个堆顶取平均。
我觉得最难的在于维护这两个堆,保证两个堆的元素刚好分别是最大的一半和最小的一半:

  • 元素先进入最大堆(存小数)
  • 然后取最大堆的top一一进入最小堆(存大数)
  • 如果最大堆的元素个数<最小堆的元素个数,将最小堆的top给最大堆

这样能保证最大堆的元素个数>=最大堆的

import java.util.*;

public class Solution {
    private PriorityQueue<Integer> max = new PriorityQueue<Integer>((a,b)->b-a);
    private PriorityQueue<Integer> min = new PriorityQueue<Integer>((a,b)->a-b);

    public void Insert(Integer num) {
       max.offer(num);
       min.offer(max.poll());
       if(max.size()<min.size()){
           max.offer(min.poll());
       }
    
    }

    public Double GetMedian() {
        int maxsize=max.size();
        int minsize=min.size();

        if(maxsize==minsize){//奇数
            return ((double)max.peek()+(double)min.peek())/2;
        }
        else{
            return (double)max.peek();
        }
        
    }


}

插入的时间复杂度降为了logn,getMedian为O(1)

49表达式求值

在这里插入图片描述

写起来还是很麻烦,主要是判断求值的两种情况:

  • 遇到)
  • 当前符号的优先级<=符号栈顶的优先级

总体来说分为四种情况:

  1. 遇到(直接入op栈
  2. 遇到数字要计算连续数字的值,记得最后i要减1,因为大循环也+1
  3. )可以计算
  4. ±*需要判断当前符号和栈顶的优先级,当前符号的优先级<=的时候可以计算
    注意计算的时候要while.因为可能存在多个符号需要计算
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
    Map<Character,Integer> map=new HashMap<Character,Integer>(){{
        put('-',1);
        put('+',1);
        put('*',2);
    }};

    public int solve (String s) {
        // write code here
        Stack<Integer> num = new Stack<>();
        Stack<Character> op = new Stack<>();
        num.push(0);//防止第一个是负数;
        for(int i=0;i<s.length();i++){
            //字符
            if(!Character.isDigit(s.charAt(i))){
                if(s.charAt(i)=='(') op.push('(');
                else if(s.charAt(i)==')'){
                    while(op.peek()!='('){//里面可能需要多次计算
                        cal(num,op);
                    }
                    op.pop();//去掉(             
                }else{//+-*
                    while(!op.isEmpty()&& op.peek()!='('){//里面可能需要多次计算
                        if(map.get(s.charAt(i))<=map.get(op.peek()))
                            cal(num,op);
                        else break;
                    }
                    op.push(s.charAt(i));
                }

            }else{//数字
                int num1 = 0;
                while(i<s.length()&&Character.isDigit(s.charAt(i))){
                    num1=num1*10+s.charAt(i)-'0';
                    i++;
                }
                //因为大循环再加一次
                i--;
                num.push(num1);
            }
        }
        while (!op.isEmpty() && op.peek() != '(') cal(num, op);//把剩下的算完
        return num.pop();
    }

    public void cal(Stack<Integer> num, Stack<Character> op){
        int right = num.pop();
        int left = num.pop();
        int res=0;
        switch(op.pop()){
            case '+': 
                res = left+right;
                break;
            case '-': 
                res = left-right;
                break;
            case '*': 
                res = left*right;
                break;
        }
        num.push(res);
    }
}

时间和空间复杂度都是O(n)

50 两数之和

在这里插入图片描述
这题印象很深刻,用哈希表存target出现过的数和对应的索引即可,时间和空间复杂度都是O(n)

import java.util.*;


public class Solution {
    /**
     * 
     * @param numbers int整型一维数组 
     * @param target int整型 
     * @return int整型一维数组
     */
    public int[] twoSum (int[] numbers, int target) {
        // write code here
        Map<Integer,Integer> m = new HashMap<>();//存值和index
        int[] res = new int[2];
        for(int i=0;i<numbers.length;i++){
            if(m.containsKey(numbers[i])){
                res[0] = m.get(numbers[i]);
                res[1] = i+1;
                break;
            }else{
                m.put(target-numbers[i],i+1);
            }
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值