牢记剑指Offer Java (六)

滑动窗口的最大值
首先暴力解为时间复杂度是O(nk)
利用辅助队列求解:

ArrayList<Integer> maxInWindows = new ArrayList<>();
Deque<Integer> deque = new Deque<>();
for(int i=0;i<size;i++){
	whlie(!index.empty() && nums[i]>nums[index.back()])
		deque.pollLast();
	deque.add(i);
}
for(int i=size; i<nums.size();i++){
	maxInWindows.add(num[deque.peek()]);
	while(!deque.empty() && nums[i]>=nums[deque.peek()])
		deque.pollLast();
	if(!deque.empty() && deque.peek()<= i-size)
		deque.poll();
	deque.add(i);
}
maxInWindows.add(nums[deque.peek()]);
return maxInWindows;

队列的最大值
前面的方法是在遍历过程中加入了一个辅助队列,遍历过程就是push加pop的过程,现在要和第30题一样,把辅助队列写进队列的方法里。

public T max(){
	if(max.empty())
          return null;
     return maximum.peek().value;
}
private int currentIndex = 0;
public void push(T number){
	while(!max.empty() && number>=max.peek().number)
		deque.pollLast();
	InternalData internalData = {number, currentIndex};
	data.add(internalData);
	max.add(internalData);
}
public void pop(){
	if(max.peek().index == data.peek().index)
		max.poll();
	data.poll();
}

理解:滑动窗口最大值就是队列的最值问题,而包含min的栈就是栈的最值问题(都是添加一个新的数据结构来记录最值)。
不同的是(以最大值为例):

  • 栈的最大值用辅助栈,只有下个数更大才会压入,这样栈顶记录着递减的最大值。
    同时,因为有些数字没有压入,所以当没有数字压入时,min.push(min.top()),保证弹出时栈顶一直是最大元素;
  • 队列的最大值用辅助队列,如果下个数更大,则弹出辅助队列中所有小于的数再插入,这样队列也记录着递减的最大值。
    但队列怎么保证弹出问题呢?这里我们利用索引是否小于 i-size 来弹出。if(deque.peek()<=i-size) deque.poll;

Java队列总结
deque.poll–pop
deque.add–push
deque.peek–front

n个骰子的点数

public void printProbability(int number) {
    if(number<1)
        return ;
    int g_maxValue=6;
    int[][] probabilities=new int[2][];
    probabilities[0]=new int[g_maxValue*number+1];
    probabilities[1]=new int[g_maxValue*number+1];
    int flag=0;
    // 当第一次抛掷骰子时,有6种可能,每种可能出现一次
    for(int i=1;i<=g_maxValue;i++)
        probabilities[0][i]=1;

    //从第二次开始掷骰子,假设第一个数组中的第n个数字表示骰子和为n出现的次数,
    for(int k=2;k<=number;++k) {
        for(int i=0;i<k;++i)
            // 第k次掷骰子,和最小为k,小于k的情况是不可能发生的,令不可能发生的次数设置为0!
            probabilities[1-flag][i]=0;
        // 第k次掷骰子,和最小为k,最大为g_maxValue*k
        for(int i=k;i<=g_maxValue*k;++i) {
            // 初始化,因为这个数组要重复使用,上一次的值要清0
            probabilities[1-flag][i]=0;
            for(int j=1;j<=i && j<=g_maxValue;++j)
                probabilities[1-flag][i]+=probabilities[flag][i-j];
        }
        flag=1-flag;
    }
    double total=Math.pow(g_maxValue, number);
    for(int i=number;i<=g_maxValue*number;i++) {
        double ratio=(double) probabilities[flag][i]/total;
        System.out.println(i);
        System.out.println(ratio);
    }
}

扑克牌中的顺子

public boolean isContinuous(int [] numbers) {
    if (numbers == null || numbers.length == 0)
        return false;
    int count = 0;
    int diff = 0;
    Arrays.sort(numbers);
    for (int i = 0; i < numbers.length - 1; i++) {
        if (numbers[i] == 0) {
            count++;
            continue;
        }
        if (numbers[i] != numbers[i+1]) {
            diff += numbers[i+1] - numbers[i] - 1;
        } else {
            return false;
        }
    }
    if (diff <= count)
        return true;
    return false;
}

求1+2+3+…+n,要求不能使用乘除法

solve(int n){
	int result = n;
	boolean temp = (n>0) && (result += solve(n-1)>0);
	return result;
}

思路:巧用&&

不用加减乘除做加法:位运算

public int Add(int num1,int num2) {
    while (num2 != 0) {
        // 计算个位
        int sum = num1 ^ num2;
        // 计算进位(1+1)
        num2 = (num1 & num2) << 1;
        num1 = sum;
    }
    return num1;
}

字符串转数字

int i = 0;
boolean minus = false;
if(digit[i] == '+')
	i++;
else if(digit[i] == '-'){
	i++;minus = true;
}
//while(digit[i]!='\0')
for(; i<digit.length; i++){
	if(digit[i]>='0' && digit[i]<='9')
		if((!minus && number>0x7FFFFFFF)||(minus && num<0x80000000)) break;
		number = number*10 + (int)digit[i];
	else 
		break;
if(minus)
	number = -number;
return number;	

代码结构 i…minus…if…else if…for………if…return

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值