• 【数组】数组序号转换


    题目描述

    给你一个整数数组 arr ,请你将数组中的每个元素替换为它们排序后的序号。序号代表了一个元素有多大。序号编号的规则如下:

    • 从1 开始编号。
    • 元素越大,序号越大。如果两个元素相等,那么序号相同。
    • 每个数字的序号都应该尽可能地小。

    示例 1:

    输入:arr = [50,10,20,40]
    输出:[4,1,2,3]
    解释:50 是最大的元素。 10 是最小的元素。 20 是第二小的数字。 40 是第三小的数字。

    解题思路

    方案一

    这道题使用MAP+排序是最快的,MAP记录元素和序号的关系,只需要一次排序+一次遍历就可以等到想要的结果;代码参考:

    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    
    class Solution {
        public int[] arrayRankTransform(int[] arr) {
            int[] copyArray = new int[arr.length];
            System.arraycopy(arr, 0, copyArray, 0, arr.length);
            Arrays.sort(copyArray);
            Map rankMap = new HashMap<>();
            int count = 0;
            for (int v : copyArray) {
                if (!rankMap.containsKey(v)) {
                    rankMap.put(v, ++count);
                }
            }
            int[] res = new int[arr.length];
            for (int i = 0; i < arr.length; i++) {
                res[i] = rankMap.get(arr[i]);
            }
            return res;
        }
    }

    方案二

    使用一个二维数组,对这个数组做2次排序,然后把结果拷贝出来,也可以完成,但是效率不高,这里给出参考代码:

    import java.util.Arrays;
    import java.util.Comparator;
    
    class Solution1 {
        public int[] arrayRankTransform(int[] arr) {
            if (arr.length == 0) {
                return new int[]{};
            }
            if (arr.length == 1) {
                return new int[]{1};
            }
            int[][] arr2 = new int[arr.length][3];
            for (int i = 0; i < arr.length; i++) {
                arr2[i][0] = arr[i];
                arr2[i][1] = i;
            }
    
            Arrays.sort(arr2, new Comparator() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o1[0] - o2[0];
                }
            });
    
            int count = 1;
            arr2[0][2] = 1;
            for (int i = 1; i < arr2.length; i++) {
                if (arr2[i - 1][0] == arr2[i][0]) {
                    arr2[i][2] = count;
                } else {
                    arr2[i][2] = ++count;
                }
            }
    
            Arrays.sort(arr2, new Comparator() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o1[1] - o2[1];
                }
            });
    
            int[] res = new int[arr.length];
            for (int i = 0; i < res.length; i++) {
                res[i] = arr2[i][2];
            }
    
            return res;
        }
    }

    总结 

    这道题主要考察的是排序+下标的还原操作,方案一在耗时上比方案二快了3倍;主要的调整点:使用MAP减少了排序次数。

    如果想对方案一再进行排序,可以考虑优化MAP的使用,减小MAP扩容等操作导致的耗时上涨。如果有更好的方案欢迎给出。

  • 相关阅读:
    SpringSecurity中注解讲解
    使用 Apache Camel 和 Quarkus 的微服务(一)
    lv7 嵌入式开发-网络编程开发 06 socket套接字及TCP的实现框架
    Java版工程行业管理系统源码-专业的工程管理软件- 工程项目各模块及其功能点清单
    基于单片机的四层电梯仿真设计(#0012)
    Tools-反射
    Kubernetes----基于kubeadm工具在CentOS7.9虚拟机上部署一主两从类型的Kubernetes集群环境
    2022/09/12、13、14 day02/03/04:HTML和CSS(二)
    【每日一题】回文串移除方案
    Linux网络编程:详解https协议
  • 原文地址:https://blog.csdn.net/weiliuhong1/article/details/126027128