阿里巴巴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