阿里巴巴2020春招笔试题(两题)


第一题:

n个农场,第i个农场有a[i]只鸡,每天每个农场都会增加k只鸡。每晚农场主都会选择鸡最多的农场,将该农场鸡的个数除以2下取整,在m天后剩下多少只鸡?

输入:

3 3 100
100 200 400

输出:

925

解释:

(100 200 400)->(200 300 250)->(300 200 350)->(400 300 225)

(400+100)/2=250
(300+100)/2=200
(350+100)/2=225
400+300+225=925

第二题:

序列arr={a1,a2,...,an}的所有连续子序列最大值的期望是多少?【连续子序列为{ai,ai+1,...,aj-1,aj},输出取六位有效数字】

输入:

3     //表示序列的个数
1 2 3  //表示序列的值

输出

2.333333

解释:

连续子序列:
{1,2,3}->{1},{2},{3},{1,2},{2,3},{1,2,3} 最大值: {1}:1 {2}:2 {3}:3 {1,2}:2 {2,3}:3 {1,2,3}:3 将最大值求和取平均值:(1+2+3+2+3+3)/6=2.333333

 

解答:

第一题:

public class Test1 {

    /**
     *思路:
     *  同步增加就相当于不增加,到最后一起增加
     *步骤:  
     *  1.每次取优先队列最大值max,然后减去(需要减去的值也就是)当前为i天则(i*k+max)/2上取整,最后将值放回优先队列中
     *  2.最终将优先队列中的值全相加再加上同步增加的值(m*n*k)
     */
    //n,m,k,a[i]
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int k = sc.nextInt();

        PriorityQueue<Integer> queue = new PriorityQueue<>(n, (o1, o2) -> o2 - o1);

        for (int i = 0; i < n; i++) {
            queue.add(sc.nextInt());
        }

        //每次取优先队列最大值max,然后减去(需要减去的值也就是)当前为i天则(i*k+max)/2上取整,最后将值放回优先队列中
        for (int i = 1; i <= m; i++) {

            int tmp = queue.poll(); //获得没有更新的最大值
            int num = tmp + i * k;  //获得真实的最大值
            num -= num / 2;         //获得一半的上界
            tmp -= num;             //(没有更新的最大值)减去(需要减去的真实上界一半的值)
            queue.add(tmp);
        }

        //最终将优先队列中的值全相加再加上同步增加的值(m*n*k)
        int result = m * n * k + queue.stream().mapToInt(e -> e).sum();

        System.out.println(result);
    }
}

 第二题:

方法一:动态规划【时间复杂度最差O[n*n]】

import java.util.HashMap;
import java.util.Scanner;

public class Test2 {

    //输入:3
    //输出:1 2 3
    //思路:动态规划
    //  使用map保留前n项所有子序列集合的最大值(key)和出现次数(value),在第n+1项时将map中的key与a[n+1]比较
    //1.若key比a[n+1]大则计算key与value的乘积,累加到result结果中
    //2.若key比a[n+1]小则将key对应的value值加到a[n+1]对应的value值上,并清空原来key对应的值
    //3.最终将a[n+1]乘上对应的value,累加到result结果中
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }

        int all = n * (n + 1) / 2;
        double result = 0;

        //保留最大值,以及最大值出现的次数
        HashMap<Integer, Integer> maxValue = new HashMap<>(n);

        for (int i = 0; i < n; i++) {
            if (maxValue.containsKey(a[i])) {
                maxValue.put(a[i], maxValue.get(a[i]) + 1);
            } else {
                maxValue.put(a[i], 1);
            }

            int count = maxValue.get(a[i]);

            for (Integer key : maxValue.keySet()) {

                if (key > a[i]) {   //之前子序列最大值大于a[i],则子序列最大值不变
                    result += key * maxValue.get(key);
                } else if (key < a[i]) {  //之前子序列最大值小于a[i],则将原来子序列的值加到a[i]为key的值上,并清空原来子序列值
                    count += maxValue.get(key);
                    maxValue.put(a[i], count);
                    maxValue.put(key, 0);
                }
            }
            //最后将以a[i]为最大值的子序列个数乘以a[i]
            result += a[i] * count;
        }

        //求期望并调整有效位
        result /= all;
        result = (long) (result * Math.pow(10, 6)) / Math.pow(10, 6);
        System.out.println(result);
    }
}

 方法二:单调栈【时间复杂度最差O(n+n)】

import javafx.util.Pair;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Test2 {

    //输入:3
    //输出:1 2 3
    //思路:单调栈
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        int all = n * (n + 1) / 2;
        double result = 0;

        /**
         * List<AbstractMap.SimpleEntry<Integer, Integer>> list1 = new ArrayList<>();
         * list1.add(new AbstractMap.SimpleEntry<>(1, 1));
         * 等价于
         * List<Pair<Integer, Integer>> list = new ArrayList<>();
         * list.add(new Pair<>(1,1));
         */
        //单调递减栈
        List<Pair<Integer, Integer>> list = new ArrayList<>();
        int listSize = list.size();
        int listValue = 0;

        for (int i = 0; i < n; i++) {

            int num = sc.nextInt();
            int count = 1;

            for (int j = listSize - 1; j >= 0; j--) {
                if (list.get(j).getKey() > num) {
                    break;
                } else {
                    count += list.get(j).getValue();
                    listValue -= list.get(j).getKey() * list.get(j).getValue();
                    list.remove(j);
                    listSize--;
                }
            }

            list.add(new Pair<>(num, count));

            listValue += num * count;
            result += listValue;
            listSize++;

        }


        //求期望并调整有效位
        result /= all;
        result = (long) (result * Math.pow(10, 6)) / Math.pow(10, 6);
        System.out.println(result);
    }
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM