506. Relative Ranks

给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌。前三名运动员将会被分别授予 “金牌”,“银牌” 和“ 铜牌”("Gold Medal", "Silver Medal", "Bronze Medal")。

(注:分数越高的选手,排名越靠前。)

示例 1:

输入: [5, 4, 3, 2, 1]
输出: ["Gold Medal", "Silver Medal", "Bronze Medal", "4", "5"]
解释: 前三名运动员的成绩为前三高的,因此将会分别被授予 “金牌”,“银牌”和“铜牌” ("Gold Medal", "Silver Medal" and "Bronze Medal").
余下的两名运动员,我们只需要通过他们的成绩计算将其相对名次即可。

提示:

  1. N 是一个正整数并且不会超过 10000。
  2. 所有运动员的成绩都不相同。

=====================================================================

Review:

第一反应是使用哈希表去储存分数与原位置的对应关系,排序后使用分数进行查找

或者排序后进行二分查找(这个会慢一些)

class Solution {
    public String[] findRelativeRanks(int[] nums) {
        final HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i],i);
        }
        Arrays.sort(nums);
        String[] result = new String[nums.length];
        for (int i = nums.length-1,p=1; i > -1; i--,p++) {
            if (p==1){
                result[map.get(nums[i])] = "Gold Medal";
            }else if(p==2){
                result[map.get(nums[i])] = "Silver Medal";
            }else if(p==3){
                result[map.get(nums[i])] = "Bronze Medal";
            }else {
                result[map.get(nums[i])] = String.valueOf(p);
            }
        }
        return result;
    }
}

确实很简单,但是仔细想一下,这种key和value都为数字的可以避免使用hashtable 而转用数组index

那要怎么做呢?

我们可以定义一个数组, arr[ i ]元素用来储存原数组的确切位置信息,并且不改变原数组大小排列

即一个元素携带两个信息:数组下标,大小

最简单的方法就是拼接 比方说nums数组下标为5的上面值为666,那么我们可以用6660005 (个数N最大为10000)

这样我们可以对储存这种数的新数组arr进行排序,对6660005 % 10000就可以得到下标5

为了速度更快,可以使用位运算

下面是代码

========================================================

Code:

    public String[] findRelativeRanks(int[] nums) {
        final int len = nums.length;
        int digit = 1;
        while (len >> digit != 0) {
            digit++;
        }
        final long[] record = new long[len];
        for (int i = 0; i < len; i++) {
            record[i] = (long) (nums[i] << digit) + i;
        }
        Arrays.sort(record);
        String[] result = new String[len];
        int p = (1 << digit) - 1;
        for (int i = len - 1, rak = 1; i > -1; i--, rak++) {
            if (rak == 1) {
                result[(int) (record[i] & p)] = "Gold Medal";
            } else if (rak == 2) {
                result[(int) (record[i] & p)] = "Silver Medal";
            } else if (rak == 3) {
                result[(int) (record[i] & p)] = "Bronze Medal";
            } else {
                result[(int) (record[i] & p)] = String.valueOf(rak);
            }
        }
        return result;
    }

要比哈希方法快一倍

顺便吐槽一下leetcode ,更新了内存消耗后所有提交都比原来慢了许多

原本提交的答案变成了不可超越的神话???

为啥第一名 new int[99999999] 不报超内存??

拿不到100%好心塞啊

上一篇:进阶-第50__深入聚合数据分析_percentiles rank以及网站访问时延SLA统计


下一篇:js实现表格无缝滚动效果