"Algorithm Competition 300 Quick Questions" one question per day: "Arrangement Transformation"

" Algorithm Competition: 300 Quick Questions " will be published in 2024, and it is an auxiliary workbook for "Algorithm Competition" .
All questions are placed in the self-built OJ New Online Judge .
The codes are provided in C/C++, Java, and Python. The topics are mainly low-to-medium level, suitable for beginners and advanced.


" Arrangement transformation ", link: http://oj.ecustacm.cn/problem.php?id=1812

topic description

[Title Description]
  Given an arrangement a of length n, we need to change this arrangement into b.
  Each time you can select a number to move to the left several positions.
  Request the minimum number of moves.
【Input format】 .
  The first row is a positive integer n, 1≤n≤100000.
  The second line contains n integers, representing the arrangement a.
  The third row contains n integers, representing arrangement b.
【Output Format】 Output a number to represent the answer.
【Input sample】

5
5 1 3 2 4
4 5 2 1 3

【Example of output】

2

answer

  This question requires rearranging the original sequence a into sequence b. The easiest way is: directly put the numbers in a into the corresponding positions in b. This works, but obviously the number of moves is not minimal. In order to get the minimum number of moves, it is necessary to find out which numbers must be moved and which ones must not. This is related to the relative position of the numbers. For example, "5 1 3" in the example, their relative positions in a and b are the same, and they do not need to be moved; while "2" must be moved, because it is located before "1" in a and behind "1" in b.
  Analyze the new position of each number in b in a, those whose relative positions remain unchanged do not need to be moved, and those whose relative positions change need to be moved. For example, in the example a="5 1 3 2 4", to change to b="4 5 2 1 3", record the new position of the number in a as the position sequence c="2 4 5 3 1", in which the first number "5" of a moves to the "2" position of b, the second number "1" moves to the "4" position of b , and so on . c = " 2 4 5 3 1 " is the new position of a, obviously, the relative position of the number " 5 1 3" in the 3 positions of "2 4 5" in a and b remains unchanged and does not need to be moved, while the two numbers "2 4" in the position of "3 1" need to be moved left to the correct position .
  After the above analysis, the final solution to this problem is: according to the requirements of arrangement b, obtain the position sequence c; analyze each number in c, if it is smaller than the left one, move to the left, otherwise there is no need to move. This is the idea of ​​the greedy method. Computational complexity O(n).
[Notes] Master the position transformation of numbers.

C++ code

  This question is very important, it can help readers deeply understand the application of array subscripts. Lines 8, 9, and 10 of the following code complete the process of obtaining c from a and b, with the help of the subscript array id[]. This is a common technique, please master it.
  The data in this question is relatively simple, it is n numbers from 1 to n, which can be used as the subscript of the array. If it is n random numbers, you can use discretization techniques to change them into numbers in the range of 1~n.

 #include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N], c[N];
int id[N];                                     //id[x]:  数字x在b数组中的下标
int main(){
    
    
    int n;    cin >> n;
    for(int i=1; i<=n; i++)  cin >> a[i];
    for(int i=1; i<=n; i++)  cin >> b[i], id[b[i]] = i;   
    for(int i=1; i<=n; i++)  c[i] = id[a[i]];  //把a数组变成对应b数组的下标,得到位置序列c
    int ans=0, Max=0;
    for(int i=1; i<=n; i++){
    
    
        if(Max > c[i])  ans++;                 //只要c[i]左边有一个比c[i]大,则答案++
        Max = max(Max, c[i]);
    }
    cout<<ans<<endl;
    return 0;
}

java code

import java.util.Scanner;
public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        int[] a = new int[n + 1];
        int[] b = new int[n + 1];
        int[] c = new int[n + 1];
        int[] id = new int[n + 1];             //id[x]:  数字x在b数组中的下标
        for (int i=1; i<=n; i++)   a[i] = input.nextInt();        
        for (int i=1; i<=n; i++) {
    
    
            b[i] = input.nextInt();
            id[b[i]] = i;
        }
        for (int i=1; i<=n; i++)  c[i] = id[a[i]];  //把a数组变成对应b数组的下标,得到位置序列c      
        int ans = 0;
        int max = 0;
        for (int i = 1; i <= n; i++) {
    
    
            if (max > c[i])   ans++;                //只要c[i]左边有一个比c[i]大,则答案++   
            max = Math.max(max, c[i]);
        }
        System.out.println(ans);
    }
}

Python code

n = int(input())
a = [0] + list(map(int, input().split()))           #不用a[0],从a[1]开始
b = [0] + list(map(int, input().split()))           #不用b[0],从b[1]开始
id = [0] * (n + 1)                                  #id[x]:  数字x在b数组中的下标
for i in range(1, n + 1):   id[b[i]] = i
c = [0] + [id[a[i]] for i in range(1, n + 1)]       #把a数组变成对应b数组的下标,得到位置序列c
ans = 0
max_val = 0
for i in range(1, n+1):
    if max_val > c[i]:  ans += 1                    #只要c[i]左边有一个比c[i]大,则答案+1
    max_val = max(max_val, c[i])
print(ans)

Guess you like

Origin blog.csdn.net/weixin_43914593/article/details/131741061
Recommended