java 牛客网 那些插队的人+一样的水

这两道题难度不是太大,但是不去打磨代码的话容易产生超时的情况。
先来说插队的人
题意:你有一个长度为 n 的队伍,从左到右依次为 1~n,有 m 次插队行为,用数组 cutIn 进行表示,cutIn 的元素依次代表想要插队的人的编号,每次插队,这个人都会直接移动到队伍的最前方。你需要返回一个整数,代表这 m 次插队行为之后,有多少个人已经不在原来队伍的位置了。

需要把握的点:
1.如果有人多次插队,那么只需要关注他最后一次插队的情况。因为每次插队相当于重新刷新了他的位置。
2.如果10000个人排队。前8000个人有插队的行为,而后2000的人没有插队的行为。那么后2000的队列位置是没有受到影的。

代码如下:

import java.util.*;


public class Solution {
    /**
     * 计算有多少个人最终不在自己原来的位置上
     * @param n int整型 队伍总长
     * @param cutIn int整型一维数组 依次会插队到最前方的人的编号
     * @return int整型
     */
    public int countDislocation (int n, int[] cutIn) {
        // write code here
        HashSet<Integer> set = new HashSet<>();
        LinkedList<Integer> list = new LinkedList<>();
        int maxCut = Integer.MIN_VALUE;
        for(int i = cutIn.length - 1; i >= 0; i--) {
            if(!set.contains(cutIn[i])) {
                maxCut = maxCut > cutIn[i] ? maxCut : cutIn[i];
                set.add(cutIn[i]);
                list.add(cutIn[i]);
            }
        }
        int i = 0,count = 0;
        for (int l : list) {
            if(l - 1 == i) {
                count++;
            }
            i++;
        }
        if(maxCut < n) {
           return maxCut - count; 
        }else {
            return n - count; 
        }
    }
}

一样的水

题目描述
有n个水桶,第i个水桶里面水的体积为Ai,你可以用1秒时间向一个桶里添加1体积的水。
有q次询问,每次询问一个整数pi,你需要求出使其中pi个桶中水的体积相同所花费的最少时间。
对于一次询问如果有多种方案,则采用使最终pi个桶中水的体积最小的方案。

需要注意的点:1.多种最佳方案时,选择使总重量最小的情况。
2.核心思想:如果我要使n桶水一样,那么这三桶水只能变成这三个中重量最大的。
我们可以通过n*质量最大的桶 - n桶水总质量。从而求出我需要操作的时间。
那么问题也转化为我尝试所有的搭配方式找出时间最短的那个的问题。
3.操作时可以通过直接移出质量最小桶加入质量最大桶的方式来完成计算。(其实这点很关键,要不然可能会超时)
4.找到时间最短的解决方案后往桶里加水。

代码如下:

import java.util.*;


public class Solution {
    /**
     * 
     * @param n int整型 水桶的个数
     * @param q int整型 询问的次数
     * @param a int整型一维数组 n个水桶中初始水的体积
     * @param p int整型一维数组 每次询问的值
     * @return int整型一维数组
     */
    public static int[] solve (int n, int q, int[] a, int[] p) {
        // write code here
        Arrays.sort(a);
        int[] ret = new int[q];
        int count = 0;
        for (int P : p) {
            int min, st = 0, sum = 0;
            for(int k = 0; k < P; k++) {
                sum += a[k];
            }
            min = a[P - 1] * P - sum;
            for (int i = 1; i + P <= a.length; i++) {
                sum += a[i + P - 1];
                sum -= a[i - 1];
                if(min > a[i + P - 1] * P - sum) {
                    min = a[i + P - 1] * P - sum;
                    st = i;
                }
            }
            for (int i = st; i < st + P - 1; i++) {
                a[i] = a[st + P - 1];
            }
            ret[count++] = min;
        }
        return ret;
    }
}

如果你觉得对你有所帮助的话,不妨给我点个赞鼓励一下我吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值