2023 阿里云笔试题 阿里笔试 0910
笔试时间:2023年9月10日 秋招
第一题
题目
小红有一个长度为n的排列p,其中1到n的每个数都恰好出现一次,pos[i]表示排列中元素i的下标。例如p=[3,2,4,5,1],则pos =[5,2,1,3,4]。还有一个长度为m的数组a,数组的元素互不相同,即ai!=aj,。如果满足pos[ai]<pos[ai+1]<=pos[ai]+d,则认为a是一个优秀的数组。现在给定长度为n的排列p,以及长度为m的数组a1,a2...am,小红想知道最少需要多少次操作可以将数组变的不优秀,每次操作可以交换排列p的相邻元素,对应的pos数组也会发生变化。
输入描述
一行三个整数n,m,d,表示排列的长度,数组的长度以及d的值。
一行n个整数p1,p2,...,pn,表示排列p。
一行m个整数a1,a2,...am,表示数组a。
2≤m≤n≤10^5
输出描述
输出一个整数表示最少需要多少次操作。
样例输入
5 2 2
3 2 4 5 1
3 4
样例输出
1
说明
只需要交换4,5得到p=[3,2,5,4,1],这样a=[3,4]就不是优秀数组了。
参考题解
记录数组p中每个数的下标,然后遍历a数组,查出来a数组连续两个数在p数组中的下标,然后计算破坏他们的优秀关系需要的次数即可。互相远离:(p1 + d + 1-p2),互相接近:(p2-p1)。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; int main() { int n, m, d; cin >> n >> m >> d; vector<int> elements(m + 1); map<int, int> positions; for (int i = 1; i <= n; i++) { int element; cin >> element; positions[element] = i; } for (int i = 1; i <= m; i++) { cin >> elements[i]; } int minDifference = INT_MAX; for (int i = 1; i < m; i++) { int element1 = elements[i]; int position1 = positions[element1]; int element2 = elements[i + 1]; int position2 = positions[element2]; int diff1 = position2 - position1 - 1; int diff2 = min(position1 + d - 1, n - position2) + 1; int currentDifference = min(diff1, diff2); minDifference = min(currentDifference, minDifference); } cout << minDifference << endl; return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.*; class DisjointSetProblem { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int m = scanner.nextInt(); int d = scanner.nextInt(); int[] elements = new int[m + 1]; Map<Integer, Integer> positions = new HashMap<>(); for (int i = 1; i <= n; i++) { int element = scanner.nextInt(); positions.put(element, i); } for (int i = 1; i <= m; i++) { elements[i] = scanner.nextInt(); } int minDifference = Integer.MAX_VALUE; for (int i = 1; i < m; i++) { int element1 = elements[i]; int position1 = positions.get(element1); int element2 = elements[i + 1]; int position2 = positions.get(element2); int diff1 = position2 - position1 - 1; int diff2 = Math.min(position1 + d - 1, n - position2) + 1; int currentDifference = Math.min(diff1, diff2); minDifference = Math.min(currentDifference, minDifference); } System.out.println(minDifference); } }
Python:[此代码未进行大量数据的测试,仅供参考]
n, m, d = map(int, input().split()) elements = [0] * (m + 1) positions = {} for i in range(1, n + 1): element = int(input()) positions[element] = i for i in range(1, m + 1): elements[i] = int(input()) min_difference = float('inf') for i in range(1, m): element1 = elements[i] position1 = positions[element1] element2 = elements[i + 1] position2 = positions[element2] diff1 = position2 - position1 - 1 diff2 = min(position1 + d - 1, n - position2) + 1 current_difference = min(diff1, diff2) min_difference = min(current_difference, min_difference) print(min_difference)
第二题
题目
小红有一个长度为n的数组a,小红可以对数组a进多次操作。每次操作,使每个数,ai加上i,例如数组[1,1,4,5,1,4],操作一次后变成 [2,3,7,9,6,10]。现在小红想要最少的操作次数使的数组a变为严格升序,这个最少的操作次数是多少?数组a严格升序,需要满足 a1 <a2 < a3 <...< an。
输入描述
第一行输入一个整数n。
第二行输入n个整数ai。
1<=n,ai<=10^5
输出描述
输出一个整数
样例输入
6
1 1 4 5 1 4
样例输出
5
说明
5次操作后数组变成[6,11,19,25,26,34].
参考题解
经典二分做法。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <vector> using namespace std; int n; vector<int> a; bool check(int i) { for (int j = 1; j < n; j++) { long long a1 = a[j] + (long long)i * j; long long a2 = a[j + 1] + (long long)i * (j + 1); if (a1 >= a2) return false; }
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2023秋招各大笔试题汇总,c++,java,python多种语言分析,解答。