京东笔试题

326 阅读2分钟

京东笔试题

题目: 现在又n块积木,小明知道每块的重量,任意一个积木要想堆在另一个积木上:

条件:1.上面的积木重量大于下面积木的重量

2.上面的积木重量 减去 下面的积木重量 不超过x

3.最下面的积木重量没有要求

现在小明有n个积木,小明还可以获得k个魔法积木(可以变成任意重量),小明希望尽可能多的积木堆在一起,找出最好方法。

[7,4,1,9,13] x = 3, k = 0 两堆 (第一堆是1,4,7,9 ;第二堆是13)

思路:先不考虑魔法积木,则解法应该为将数组arr排序(1,4,7,9,13)依次垒上(不超过x)

现在又有k个魔法积木,我们可以使得9和13之间相容 变为一堆。

如:arr = [1,3,7,9,11,11,25,27,59] ; x = 3; k = 4;

不考虑魔法积木:

第一堆:[1,3]

第二堆:[7,9,11,11]

第三堆:[27,27]

第四堆:[59]

现在魔法积木如果融合一二堆:需要一块(7 - 3)

如果融合二三堆:需要四块(25 - 11 = 14; 四块分别是14,17,20,23)

如果融合三四堆:需要更多块

反正不管我们融合哪辆堆,堆的数量都是减一,既然收益相同,我们要选择代价最低的即融合一二堆。

代码:

 public static int minSplit(int[] arr,int k,int x) {
        Arrays.sort(arr);
        int n = arr.length;
        int[] needs = new int[n];           //一个堆最上面的与下一个堆最下面之间的重量差
        int size = 0;                       //needs数组的长度
        int splits = 1;                     //一共有几堆
        for (int i = 1; i < n; i++) {
            if (arr[i] - arr[i - 1] > x) {
                needs[size++] = arr[i] - arr[i - 1];  
                splits++;
            }
        }
        if (splits == 1 || x == 0 || k == 0) {
            return splits;
        }
        //视图去利用魔法积木,融合堆
        Arrays.sort(needs,0,size);             //排序使得需要魔法积木少的 排在前面
        for (int i = 0; i < size; i++) {
            int need = (needs[i] - 1) / x;      //如果融合起来需要几块魔法积木
            if (k >= need) {
                splits--;             //如果k可以融合,堆得数量减一
                k -= need;  //魔法积木也减去相应的个数
            } else {
                break;//魔法积木数量不够,因为升序所以直接退出循环
            }
        }
        return splits;
    }