【春招笔试】2024-04-20-阿里云-三语言题解

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员

✨ 本系列打算持续跟新阿里云近期的春秋招笔试题汇总~

💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导

👏 感谢大家的订阅➕ 和 喜欢💗

✨ 笔试合集传送们 -> 🧷春秋招笔试合集

alt

🎊 01.最短等价子串

问题描述

K 小姐接到了一个字符串处理的任务。给定一个长度为 的小写字母字符串 ,定义字符串的权值为相邻两个字符相同的对数。例如,字符串 aaabbc 的权值为 3。

现在,K 小姐需要在字符串 中找到一个长度最短的子串,使得该子串的权值恰好等于 。你能帮助她完成这个任务吗?

输入格式

第一行包含两个正整数 ,分别表示字符串 的长度和目标权值。

第二行包含一个长度为 的字符串 ,仅由小写字母组成。

输出格式

输出一个整数,表示满足条件的最短子串的长度。如果不存在这样的子串,则输出 -1。

样例输入

6 2
aaabbc

样例输出

3

数据范围

题解

本题可以使用双指针算法求解。我们用两个指针 分别表示当前子串的起点和终点。初始时,两个指针都指向字符串的起点。

我们不断地向右移动指针 ,直到当前子串的权值大于等于 。此时,我们尝试向右移动指针 ,缩小当前子串的长度,直到子串的权值恰好等于 。在这个过程中,我们记录下满足条件的最短子串长度。

重复这个过程,直到指针 到达字符串的末尾。最终得到的最短子串长度即为答案。

参考代码

  • Python
n, k = map(int, input().split())
s = input()

res = 0
ans = n + 1
i = 0
j = 1

while i < n:
    if i > 0 and s[i] == s[i - 1]:
        res -= 1
    
    while j < n and res < k:
        if s[j] == s[j - 1]:
            res += 1
        j += 1
    
    if res == k:
        ans = min(ans, j - i)
    
    i += 1

print(ans if ans != n + 1 else -1)
  • Java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        String s = sc.next();
        
        int res = 0;
        int ans = n + 1;
        int i = 0;
        int j = 1;
        
        while (i < n) {
            if (i > 0 && s.charAt(i) == s.charAt(i - 1)) {
                res--;
            }
            
            while (j < n && res < k) {
                if (s.charAt(j) == s.charAt(j - 1)) {
                    res++;
                }
                j++;
            }
            
            if (res == k) {
                ans = Math.min(ans, j - i);
            }
            
            i++;
        }
        
        System.out.println(ans == n + 1 ? -1 : ans);
    }
}
  • Cpp
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    string s;
    cin >> s;
    
    int res = 0;
    int ans = n + 1;
    int i = 0;
    int j = 1;
    
    while (i < n) {
        if (i > 0 && s[i] == s[i - 1]) {
            res--;
        }
        
        while (j < n && res < k) {
            if (s[j] == s[j - 1]) {
                res++;
            }
            j++;
        }
        
        if (res == k) {
            ans = min(ans, j - i);
        }
        
        i++;
    }
    
    cout << (ans == n + 1 ? -1 : ans) << endl;
    
    return 0;
}

🎀 02.完美排列对

问题描述

K 小姐是一位数学爱好者,她正在研究排列的性质。给定一个长度为 的整数数组 ,K 小姐希望构造两个长度为 的排列 ,满足以下条件:

  1. 对于任意 ,都有
  2. 对于任意 ,都有

你能帮助 K 小姐找到这样的排列对吗?

注:排列是指一个长度为 的数组,其中 每个元素恰好出现一次。

输入格式

第一行包含一个正整数 ,表示数组 的长度。

第二行包含 个整数,表示数组 的元素,相邻两个整数之间用单个空格隔开。

输出格式

如果不存在满足条件的排列对,则输出一行,包含一个整数

否则输出两行,第一行包含 个整数,表示排列 ;第二行包含 个整数,表示排列 。相邻两个整数之间用单个空格隔开。如果存在多组解,输出任意一组即可。

样例输入

3
2 2 0

样例输出

1 3 2
3 1 2

数据范围

题解

根据题目条件,可以得到 的关系:

由条件 1 可知, 的和是固定的,都等于 。因此,可以预处理出所有可能的 对,并按照 的值进行分组。

接下来,将输入的数组 排序,然后与预处理得到的 的值进行比较。如果两个数组排序后不相同,说明无解,直接输出

如果两个数组排序后相同,则按照 数组的顺序,依次从对应的 分组中取出一对值,即可得到满足条件的排列

时间复杂度为 ,空间复杂度为

参考代码

  • Python
from collections import defaultdict

n = int(input())
a = list(map(int, input().split()))
b = a[:]
c = [abs(i - (n - 1 - i)) for i in range(n)]
mp = defaultdict(list)
for i in range(n):
    mp[c[i]].append((i, n - 1 - i))

b.sort()
c.sort()

if b != c:
    print(-1)
else:
    p = [0] * n
    q = [0] * n
    for i in range(n):
        x, y = mp[a[i]].pop()
        p[i] = x + 1
        q[i] = y + 1
    print(*p)
    print(*q)
  • Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        int[] b = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
            b[i] = a[i];
        }
        
        in

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

学长刷题笔记 文章被收录于专栏

这里收集了超全的刷题笔记,欢迎大家的订阅,会持续跟新的

全部评论

相关推荐

10-14 15:59
武汉大学 Java
点赞 评论 收藏
分享
菜鸡鸡啊:1 1 1 0 你们现在pdd官网状态是什么呀? 我是待笔试
投递拼多多集团-PDD等公司10个岗位
点赞 评论 收藏
分享
小嘻米:好好好都不做是吧😇
投递阿里巴巴控股集团等公司10个岗位
点赞 评论 收藏
分享
10-10 20:38
山东大学 C++
Yveltals:第一题用multiset维护字母数量有序,每次取最大的数减二、最小的数减一,直到集合数量<2 或 最大值<2为止。 第三题并查集维护联通图(顶点集合),用multiset维护这些连通图的大小逆序,每次合并时,从中删掉两个子连通图的大小的值,插入合并后新值。查询时返回集合第k个即可。
投递阿里云等公司10个岗位
点赞 评论 收藏
分享
1 4 评论
分享
牛客网
牛客企业服务