阿里3.30笔试第一题

题目就不说了,其他地方也有,我觉得关键是要自己实现一个大顶堆,如果只用Java.Util包的PriorityQueue,并没有提供直接修改堆内数据的接口,所以要每个元素增加k的话,就要把元素全部弹出来放数组,加完再放回去,我今天这样做然后就超时了😪😪,痛定思痛地回去用数组自己实现了个堆去解。
public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int k = sc.nextInt();
        int[] arr = new int[n];
        int ans = 0;
        for(int i=0;i<n;i++){
            arr[i] = sc.nextInt();
        }
        
        BuildHeap(arr);
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++)//这里可以在堆中直接遍历增加k
                arr[j] += k;

            arr[0]/=2;//取堆顶元素除以2
            Heapify(arr,0,n);//再次调整堆
        }
        for(int i:arr)
           ans+=i;
        System.out.println(ans);
}
//建立大顶堆
public static void BuildHeap(int[] arr){
        for(int i=arr.length/2;i>=0;i--){
            Heapify(arr,i,arr.length);
        }
    }
//调整堆
public static void Heapify(int[] arr,int i ,int len){
        int left = i*2+1;
        int right = i*2+2;
        int largest = i;
        if(left<len && arr[left]>arr[largest]) largest = left;
        if(right<len && arr[right]>arr[largest]) largest = right;
        if(largest!=i){
            swap(arr,i,largest);
            Heapify(arr,largest,len);
        }
}

public static void swap(int[] arr , int a , int b) {
        int t = arr[a];arr[a]=arr[b];arr[b]=t;
}
如有错误,希望大佬指正!!

#阿里笔试2020##阿里巴巴##笔试题目#
全部评论
第一个回复有笔误,是((top+i*k)/2)-i*k加入队列
1 回复 分享
发布于 2020-04-03 08:56
我第一次就是自己实现堆的,这样每次增加还是要有线性复杂度,只能AC70%,这题每次循环复杂度只能是O(logn)。 我采用的方式是使用STL的优先级队列。 比较巧妙的思路是:对于第i天,队列中的元素都加上i*k才是每个元素的真实值。每天 要把最大元素的数量减半的话,就先把top弹出,再将((top+i*k)/2)+i*k加入优先级队列。这样的话还是维持着这个每个元素加上i*k是真实值的性质。 最后一一弹出所有元素求和得到sum,sum+m*n*k就算最终答案。AC
点赞 回复 分享
发布于 2020-04-03 08:48
如果每次遍历堆中元素+k,那么复杂度和暴力法不用堆只用数组并没有区别。
点赞 回复 分享
发布于 2020-04-03 08:50

相关推荐

Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
3 2 评论
分享
牛客网
牛客企业服务