The application of prefix sum, starting from a NetEase written test

The application of prefix sum, starting from a NetEase written test
On August 3, I participated in the written test approved by NetEase in advance. The written test lasted 120 minutes, and then there were 10 multiple-choice questions (20 points), 4 programming questions (80 points), and 2 subjective questions (20 points). It can be said that if your programming questions are cold, it will be basically cold. No matter how well you do it, it will be useless. Therefore, it is still necessary to keep reading questions at all times.

This time, NetEase’s written test questions are still quite difficult. The four questions use different ideas. Maybe you read the questions and then read the analysis of others. Hey, it’s quite simple, but it may be completely different in the examination room. Basically, the time for each question is only 20 minutes, and we have to handle the input and output by ourselves. Since we usually give you a method when you brush Leetcode, you don’t need to consider the input and output, so some People are not very familiar with input and output, and debugging takes a lot of time, so I suggest you be familiar with standard input and output.

The question I am going to ask today is the first question in the written test of NetEase's August 3 R&D post, and it is also the simplest of the four questions. This question involves the application of prefixes and sums, so I would like to take this question to tell you about prefixes and related knowledge. If you encounter this question in the future, you can quickly kill it.

Problem Description

I will describe this question below, but the description I gave is a simplified version. In fact, when writing test questions, the description of each question is very long. Generally, the question will be given according to the actual situation. Some people may After reading for more than ten minutes, and then I don’t know what I’m going to do, I’ll give the most simplified version here.

There are n people in a class, and n elements are given. The i-th element represents the test score of the i-th student. Then m queries are made. Each query gives a value t, which means the t-th student. We output the percentage of students whose grades of the t-th classmate exceed the class, and the percentage p can be calculated as follows: p = (the number of people who do not exceed the grade of the t-th classmate) / n * 100%. When outputting, keep to 6 digits after the decimal point and need to be rounded.
Input description: Enter two numbers n and m in the first line, separated by spaces, which means n classmates and m queries. Enter n numeric values ​​ni in the second line to indicate the score of each student, and input m numeric values ​​mi in the third line to indicate which classmate is asked each time. (Note that here 2<=n, m<=100000, 0<=ni<=150, 1<=mi<=n)
Output description: output m rows, and each row outputs a percentage p, which represents more than a percent of the class Few people.
Example 1:
Input:
3 2
50 60 70
1 2
Output
33.333333%
66.666667%

The first question is roughly like this, but it is not exactly the same as the original question. There is a slight difference between input and output, because I forgot the specific input and output. My description says that the simplification seems to be quite long, but the original question is even longer.

answer

So is this problem difficult? It's not difficult to tell the truth, but it is better for you to think about how to do it yourself first, maybe you might not be able to do it in 20 minutes in the exam room.

Some people say that this is not easy. Every time I ask, I traverse everyone's scores. The time complexity is O(n * m). Obviously, if you do this, you will definitely fail. Yes, it will time out. The general violence method can pass 20% ~ 30% of the test effort, if a question is 20 points, 4 ~ 6 points can be obtained. If you have no idea, then violence is also a good choice.

1. Dichotomy

I did this question using the dichotomy, which is to sort everyone's scores first, but when sorting, we need to open a new array to store. Then each query can be matched by binary search. Because sorting is used, it takes O(nlogn) time, and m queries take approximately O(mlogn) time. So the average time complexity can be regarded as O((m+n)logn). This time complexity passes all test cases, and the code is as follows (you can understand it if you haven't learned java):

public class Main {
    // 主函数,相当于c语言的main方法
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int m = in.nextInt();
        int n = in.nextInt();
        // 存放成绩的数组
        int[] a = new int[n];
        // 存放排序过后的成绩
        int[] b = new int[n];
                // 输入 n 个人的成绩
        for(int i = 0; i < n; i++){
            a[i] = in.nextInt();
            b[i] = a[i];
        }
        // 排序
        Arrays.sort(b);
        // 进行查询
        for(int j = 0; j < m; j++){
            // 输入是要查询第几个同学
            int t = in.nextInt();
            // 把这个同学的分数拿出来
            int fen = a[t - 1];
            // 通过二分查找是排在第几位
            int sum = binarySearch(b, fen) - 1;
            double t = sum * 1.0 / n * 100;
            System.out.printf("%.6f\n", t);

        }
    }

    private static int binarySearch(int[] b, int fen){
        int l = 0;
        int r = b.length - 1;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(b[mid] > fen){
                r --;
            }else if(b[mid] < fen){
                l++;
            }else{
                    // 由于存在分数相同的人,所以还要往后查找
                while(mid < b.length && b[mid] == fen){
                    mid++;
                }
                return mid;
            }
        }
        return 0;
    }
}

Here to explain, I did not output the "%" sign when outputting.

Prefix and

But a better way to do this question is to use the prefix and to do it. In the question, the score of each student is not more than 150 and not less than 0, then we can use an array arr, and let arr[i] represent the number of people whose score does not exceed i. In this way, we can control the time complexity to O(n+m). Look at the code directly, it will be better understood (I will not write the input code here, use a[] to store the results, m[] to store m queries):

void f(int a[], int m[]){
    int n = a.length;
    int[] arr = new int[151];
    //先统计分数为 i 的有多少人
    for(int i = 0; i < n; i++){
        arr[a[i]]++;
    }
    // 接着构造前缀和
    for(int i = 1; i < 151; i++){
        arr[i] = arr[i] + arr[i-1];
    }
    // 进行 m 次询问
    for(int i = 0; i < m.length; i++){
        // 取出成绩
        int score = a[m[i]-1];
        // 有多少人的成绩不超过 score的
        int sum = arr[score];
        System.out.printf("%.6f\n", sum * 1.0 / n * 100 );
    }
}

This method is called prefix sum, which is much simpler. Of course there are other applications of prefix and, for example:

If you give you an array arr[], and then make m queries, enter two numbers i, j for each query (i <= j). You are required to output the sum of the interval arr[i] ~ arr[j]. At this time, the prefix sum can be used. The construction of the prefix sum is also very well constructed, for example, arr[] becomes the construction of the prefix sum as follows

for(int i = 1; i < arr.length; i++){
   arr[i] = arr[i] + arr[i-1];
}

The prefix and seem to be quite simple, but there may be unexpected effects in doing the questions, such as this written test, so I will explain it to you today.

Finally, I will ask you a question similar to prefix and, I will give you a sequence of length n a1, a2, a3...an, and ask for m operations on a[i]~a[j]:

Operation 1: Add P to all the elements in a[i]~a[j]

Operation 2: Subtract P from all the elements in a[i]~a[j]

Finally, a query is given to find the sum of the elements in a[i]-a[j].

What would you do with this? At this time, the knowledge of difference is involved, but it is similar to prefix and, if you are interested, you can study it.

At last

Here are a few suggestions about the written test questions, because most of the written test questions require us to process input and output, and like Leetcode, Jianzhi offers do not require us to deal with these, so they will be unfamiliar, so I suggest that you can go to the previous years Get familiar with the real question.

There is also that most of them can be directly violent, and then they can get 20%~30% of the score. After ten minutes of thinking, there is still no good idea. Direct violence is recommended.

In addition, sometimes you are not allowed to use the local IDE for the written test, so I suggest that when writing the questions, you can directly type the code on the web page instead of running to the local IDE to type and paste it.

The three questions at the end of the NetEase written test are quite difficult. If you are interested, I will release them another day and analyze them appropriately. Of course, I did poorly in the written test... Only two ACs were awarded, and the other two were direct violence to get points.

You might like
1. After telling a story, the Hash prehistoric ***
2. Why can't you learn recursion? Say goodbye to recursion and talk about some of my experiences.
3. An article to understand how a computer sends data to another computer.
4. How to find the most frequent occurrence from 20/40/80 billion integers with only 2GB of memory Number
5. String matching Boyer-Moore algorithm: How is the search function in the text editor implemented?
The application of prefix sum, starting from a NetEase written test

Guess you like

Origin blog.51cto.com/15015171/2554958