Likou——Analysis of Array Serial Number Conversion Ideas

Topic:
Give you an integer array arr, please replace each element in the array with their sorted serial number.
The serial number represents how big an element is. The serial numbering rules are as follows:

  • The serial number starts from 1.
    The larger an element, the larger the sequence number. If two elements are equal, then their sequence numbers are the same.
    The serial number of each number should be as small as possible.
  • Example 1:
    Input: arr = [40,10,20,30]
    Output: [4,1,2,3]
    Explanation: 40 is the largest element. 10 is the smallest element. 20 is the second smallest number. 30 is the third smallest number.
  • Example 2:
    Input: arr = [100,100,100]
    Output: [1,1,1]
    Explanation: All elements have the same sequence number.
  • Example 3:
    Input: arr = [37,12,28,9,100,56,80,5,12]
    Output: [5,3,4,2,8,6,7,1,3]

Problem-solving idea 1 : First read the title. I think this should be a very simple sorting problem. We only need to filter out the duplicate elements in the original array, then sort the remaining elements, and then traverse the original array through each element in the sorting The position in the list can be compared with the serial number assignment to get the correct answer, so I started to write the algorithm according to this idea.
Encountered problem 1 : Although this algorithm has a clear idea of ​​solving the problem, because the algorithm is too inefficient and the calculation time is too long, it is stuck in the last test case and eventually ended in failure.

package 力扣;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;



public class 数组序号转换 {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    2,-11,24,15,26,-31,-48,-49,22,37,-36};
        arrayRankTransform(arr);
    }
    public static int[] arrayRankTransform(int[] arr) {
    
    
        ArrayList list = new ArrayList();
        int s = arr.length;
        //1.用于过滤重复数组元素
        for (int i = 0; i < s; i++) {
    
    
            if (!list.contains(arr[i])){
    
    
                list.add(arr[i]);
            }
        }
        int temp = list.size();
        //2.转为数组之后进行排序
        Object[] brr = list.toArray();
        Arrays.sort(brr);
        //3.对于原数组遍历寻找在排序位置的值然后标记
        for (int i = 0; i < s; i++) {
    
    
            for (int j = 0; j < temp; j++) {
    
    
                if (arr[i] == (int)brr[j]){
    
    
                    arr[i] = j+1;
                    break;
                }
            }
        }
        //4.输出相应的值(提交代码时请删掉)
        for (int i = 0; i < s; i++) {
    
    
            System.out.print(arr[i]+",");
        }
        return arr;
    }
}

Problem-solving idea 2 : After summarizing the experience of the first algorithm, I think I should change the way of thinking to solve the problem, so I thought about whether a two-dimensional array can be used to record the value and serial number of the original array separately, first using the original array elements The value size is sorted, and then the element values ​​are replaced with their current order, and finally the original order of the original array value is sorted, so that the number of each element in the sorting column can be obtained in order, and the first is optimized. One algorithm compares the low efficiency of traversal search after sorting.
Encountered problem 2 : First of all, in this algorithm, I got stuck in the test value of the empty array of [], and an error was reported because the array was out of bounds. So I added two cases for judging the length of the array, but in the end it was because The algorithm timed out, was too inefficient and ended in failure.

package 力扣;
import java.util.Arrays;

public class 数组序号转换优化 {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    19,22,-47,24,-37};
        arr = arrayRankTransform(arr);
        for (int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]+" ");
        }
    }
    public static int[] arrayRankTransform(int[] arr) {
    
    
        int s = arr.length;
        if (s != 0){
    
    
            int[][] brr = new int[2][s];
            int add = 1;
            int i = 0,j = 0;
            //1.用二维数组来存储一维数组,第二层表示序号
            for (i = 0; i < s; i++) {
    
    
                brr[0][i] = arr[i];
                brr[1][i] = add++;
            }
            //比较数字
            int temp = 0;
            //下标记录
            int flag = 0;
            //2.先以原数组进行排序
            for (i = 0; i < s-1; i++) {
    
    
                temp = brr[0][i];
                flag = i;
                for (j = i; j < s; j++) {
    
    
                    if(brr[0][j] < temp){
    
    
                        temp = brr[0][j];
                        flag = j;
                    }
                }
                int temp1 = brr[0][i];
                int temp2 = brr[1][i];
                brr[0][i] = brr[0][flag];
                brr[1][i] = brr[1][flag];
                brr[0][flag] = temp1;
                brr[1][flag] = temp2;
            }
            //3.进行位序替换
            add = 1;
            temp = brr[0][0];
            brr[0][0] = add;
            for (int k = 1; k < s; k++) {
    
    
                if(brr[0][k] != temp){
    
    
                    temp = brr[0][k];
                    brr[0][k] = ++add;
                }else{
    
    
                    brr[0][k] = add;
                }
            }
            //4.再以序号原数组进行排序
            for (i = 0; i < s-1; i++) {
    
    
                temp = brr[1][i];
                flag = i;
                for (j = i; j < s; j++) {
    
    
                    if(brr[1][j] < temp){
    
    
                        temp = brr[1][j];
                        flag = j;
                    }
                }
                if(flag != i){
    
    
                    int temp1 = brr[0][i];
                    int temp2 = brr[1][i];
                    brr[0][i] = brr[0][flag];
                    brr[1][i] = brr[1][flag];
                    brr[0][flag] = temp1;
                    brr[1][flag] = temp2;
                }
            }
            return brr[0];
        }
        else{
    
    
            return arr;
        }
    }
}

Problem-solving idea 3 : Finally, I found a super-optimized problem-solving idea in the comment area of ​​browsing the problem-solving. The original author explained his idea like this: Detailed code explanation
Insert picture description here


    public static int[] arrayRankTransform(int[] arr) {
    
    
        //分别设置最大无穷和最小无穷
        int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
    //分别找出数组中最小和最大值存入min和max当中
        for (int num : arr) {
    
    
            if (num < min) min = num;
            if (num > max) max = num;
        }
    //创建数组,容量为最大值减去最小值+1
        int[] count = new int[max - min + 1];
    //遍历数组,在原数组每项值减去最小值的位置处赋值1
        for (int num : arr)
            count[num - min] = 1;
    //创建数组,容量为最大值减去最小值+2
        int[] preSum = new int[count.length + 1];
    //遍历preSum数组,将每个位置赋值是preSum[i - 1] + count[i - 1]
        for (int i = 1; i < preSum.length; i++)
            preSum[i] = preSum[i - 1] + count[i - 1];
    //创建数组,容量为原数组长度
        int[] ans = new int[arr.length];
        int index = 0;
        for (int num : arr)
            ans[index++] = preSum[num - min] + 1;
        return ans;
    }

Code understanding : The author’s code is indeed very concise and concise, but it seems a bit difficult to understand. I add comments to the author’s code, and then analyze it sentence by sentence. I have my own understanding. First, the author wants to use the bucket sorting algorithm to deal with Huge arrays are sorted to improve efficiency. I also deliberately checked this sorting algorithm. The overall idea is that for unordered arrays, the buckets are split by range, and then sorted in the buckets and then spliced.

  1. The first key is that we must first know how to customize the size of the bucket range, that is, determine the maximum and minimum values ​​in the array.
  2. Then create the bucket. We make sure that there is only one element in each bucket. This is quite a recursive algorithm to the final exit. The author thought of using each value in the array minus the minimum number as the bucket sign, and then create Assign him a value of 1 in the count array.
  3. Since the larger the number, the larger the value obtained by subtracting the minimum value, so the above operation is equivalent to sorting the array, and then the function of the preSum array is to splice the fragmented numbers in the bucket. Since operation 2 is all assigned 1, We don’t know which number each number actually ranks in. At this time, we only need to add up each number, so that the lower the value is, the bigger it is, and every time we add one, we can clearly know The order of each element is changed.
  4. After doing the above operations, we only need to create an array with the same length as the original array, and then use the value minus the minimum value method to find the corresponding order value at the corresponding position, and save it for him.

Learning gains :

  • If you want to de-duplicate the array, you can use ArrayList
 ArrayList list = new ArrayList();
        int s = arr.length;
        //1.用于过滤重复数组元素
        for (int i = 0; i < s; i++) {
    
    
            if (!list.contains(arr[i])){
    
    
                list.add(arr[i]);
            }
        }
  • Want to get infinite minimum and infinite maximum
 //分别设置最大无穷和最小无穷
 int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;

Guess you like

Origin blog.csdn.net/baldicoot_/article/details/107249264