Task 2 Build Skyscrapers

Task 2

You are given an array A of N integers, representing the maximum heights of N skyscrapers to be built.
Your task is to specify the actual heights of the skyscrapers, given that:

  • The height of the K-th skyscraper should be positive and not bigger than A[K];
  • No two skyscrapers should be of the same height;
  • The total sum of the skyscrapers’ heights should be the maximum possible.

Write a function:

class Solution {    public int[] solution(int[] A);    }

that, given an array A of N integers, returns an array B of N integers where B[K] is the assigned height of the K-th skyscraper satisfying the above conditions.

If there are several possible answers, the function may return any of them. You may assume that it is always possible to build all skyscrapers while fulfilling all the requirements.
Examples:

  1. Given A = [1, 2, 3], your function should return [1, 2, 3], as all of the skyscrapers may be built to their maximum height.
  2. Given A = [9, 4, 3, 7, 7], your function may return [9, 4, 3, 7, 6]. Note that [9, 4, 3, 6, 7] is also a valid answer. It is not possible for the last two skyscrapers to have the same height. The height of one of them should be 7 and the other should be 6.
  3. Given A = [2, 5, 4, 5, 5], your function should return [1, 2, 3, 4, 5].

Write an efficient algorithm for the following assumptions:

  • N is an integer within the range [1…50,000];
  • Each element of array A is an integer within the range [1…1,000,000,000];
  • There is always a solution for that given input.

思路1 - 超时

  • 使用hashmap,key为要建立的高楼高度,value为高楼位置
  • 遍历原数组
  • 如果当前高楼没有建立过相同高度,则在该位置建立该高度的高楼,map.put(height, index)
  • 如果当前高楼建立过,则while循环向下寻找,最可能建立的最大高楼的高度,map.put(tmpHeight, index)
  • 以上保证尽可能高的建立高楼
  • 最后创建结果数组,遍历map,一一赋值要建立的高楼位置及其高度

复杂度

时间复杂度:O(MN), 10^9 * 5 * 10^4
空间复杂度:O(n), n < 5 * 10^4

Code

public int[] solutionTimeOut(int[] A) {
        Map resultMap = new HashMap();
        for (int i = 0; i < A.length; i++) {
            int tmp = A[i];
            while (resultMap.containsKey(tmp)) {
                tmp --;
            }
            resultMap.put(tmp, i);
        }
//        System.out.println(resultMap);

        int[] result = new int[A.length];
        Iterator iterator = resultMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            result[entry.getValue()] = entry.getKey();
        }
        return result;
    }

思路2

  • 创建sortedMap,遍历数组初始化map,key为出现的高度,value为该高度出现的重复次数
  • 更新sortedMap,key为出现的高度,value为该高度对应的最大能建立的高度 (重点)
  • 遍历原数组,遇到某高度大楼时,从map中取value为其能建立的最大高度,同时高度-1
  • 示例:
  • {2,5,4,5,5}
  • {5=3, 4=1, 2=1} - sortedMap 初始化
  • {5=5, 4=2, 2=1} - sortedMap 更新
  • [1, 5, 2, 4, 3]

复杂度

时间复杂度:O(n), n = 5 * 10^4
空间复杂度:O(n), n = 5 * 10^4

Code

    public int[] solution(int[] A) {
        //  new map => A[i] = times
        TreeMap sortedMap = new TreeMap<>(new Comparator() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        for (int i = 0; i < A.length; i++) {
            sortedMap.put(A[i], sortedMap.get(A[i]) == null ? 1 : sortedMap.get(A[i]) + 1);
        }
//        System.out.println(sortedMap);

        // update map => A[i] = maxHight
        int[] result = new int[A.length];
        Iterator iterator = sortedMap.entrySet().iterator();
        int lastMaxHieght = Integer.MAX_VALUE;
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            int currentHeight = Math.min(entry.getKey(), lastMaxHieght);
            lastMaxHieght = currentHeight - entry.getValue();
            entry.setValue(currentHeight);
        }
//        System.out.println(sortedMap);

        // set result
        for (int i = 0; i < A.length; i++) {
            result[i] = sortedMap.get(A[i]);
            sortedMap.put(A[i], sortedMap.get(A[i]) - 1);
        }
        return result;
    }

你可能感兴趣的:(算法)