第 217 场周赛

这次就做出第一题,第一题太简单就不写了,最后一题,等后面补上。
我还是太菜了,打完比赛之后写个记录的博客,为了督促自己坚持这一件事情,同时把当时错的思路和对别人写的方法的理解做个记录,方便以后回顾,多回顾帮助吸收为自己的知识。

1673. 找出最具竞争力的子序列

比赛时超时了,我记得以前有道题也是同样的意思,就是每次先留后–k个数,从前面的数中选出最小的,然后再从这个最小的值后一位开始,留–k个数,再选最小的依次类推,但是这么写超时了,比赛中没想出来用stack怎么改下面的方法。

class Solution {
    public int[] mostCompetitive(int[] nums, int k) {
        int len = nums.length;
        int[] res = new int[k];
        for(int i=0;i<k;i++){
            res[i] =Integer.MAX_VALUE;
        }
        int start = 0;
        int p=0;
        while(start<=len-k && k>0){
            int newStart = start;
            for(int cur = start;cur<=len-k;cur++){
                if(res[p]>nums[cur]){
                    res[p] = nums[cur];
                    newStart = cur;
                }    
            }
            // System.out.println("newStart:"+newStart+" res[p]:"+res[p]);
            start = newStart+1;
            k--;
            p++;
        }
        return res;
    }
}

赛后看题解,重新做了这道题

class Solution {
    public int[] mostCompetitive(int[] nums, int k) {
        Stack<Integer> stack = new Stack<Integer>();
    	stack.add(-1);
    	int len = nums.length;
    	
    	for(int i=0;i<len;i++){
    		while(nums[i]<stack.peek() && (k+1-stack.size()<len-i)){
    			stack.pop();
    		}
    		if(stack.size()<k+1){
    			stack.add(nums[i]);
    		}
    	}
    	int[] ret = new int[k];
    	while(k>0){
    		ret[--k] = stack.pop();
    	}
    	return ret;
    }
}

1674. 使数组互补的最少操作次数

差分数组

这题理解了半天,看了好多题解,大致意思是两数之和的取值范围分为几段,
1<sum<min+1:需要改变两次
min+1<=sum<min+max:需要改变一次
min+max=sum:不需要改变
min+max+1<=sum<=max+limit:只需要改变一次
max+limit+1<=sum<=limit*2:需要改变两次

所以如果sum选在
1、1~Min(nums) 那就是 2nums.length次操作数(最差的情况)
2、然后从2向右发展,遍历数组中的每个元素,如果(min+1<=sum<min+max)就在2的基础上-1;到min+max再-1;到min+max+1再+1;依次类推
3、这样遍历之后就2~2
limit,看选哪个值时改变的次数最小。

我也不知道有没有解释清楚,我也是看了题解想了很久才想明白。。

class Solution {
    public int minMoves(int[] nums, int limit) {
        int[] diff = new int[2*limit+2];
    	int len = nums.length;
    	for(int i=0;i<len/2;i++) {
    		int min = Math.min(nums[i], nums[len-1-i]);
    		int max = Math.max(nums[i], nums[len-1-i]);
    		diff[1]+=2;
    		diff[min+1]-=1;
    		diff[min+max]-=1;
    		diff[min+max+1]+=1;
    		diff[max+limit+1]+=1;
    		diff[2*limit+1]-=2;
    	}
    	int ans = len;
    	int sum=diff[1];
    	for(int i=2;i<=limit*2;i++) {
    		sum+=diff[i];
    		ans = ans>sum?sum:ans;
    	}
    	return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值