【阿里云笔试题汇总】2024-04-20-阿里云春招笔试题-三语言题解(CPP/Python/Java)

news2024/9/21 14:36:59

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

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

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

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

📧 清隆这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 清隆领取,会在飞书进行同步的跟新。

文章目录

    • 🎊 01.最短等价子串
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 🎀 02.完美排列对
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 💝 03.K小姐的森林管理
      • 题目描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 写在最后
    • 📧 清隆这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 清隆领取,会在飞书进行同步的跟新。

🎊 01.最短等价子串

问题描述

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

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

输入格式

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

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

输出格式

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

样例输入

6 2
aaabbc

样例输出

3

数据范围

1 ≤ k < n ≤ 3 × 1 0 5 1 \leq k < n \leq 3 \times 10^5 1k<n3×105

题解

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

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

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

参考代码

  • 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 小姐是一位数学爱好者,她正在研究排列的性质。给定一个长度为 n n n 的整数数组 a a a,K 小姐希望构造两个长度为 n n n 的排列 p p p q q q,满足以下条件:

  1. 对于任意 1 ≤ i ≤ n 1 \leq i \leq n 1in,都有 p i + q i = n + 1 p_i + q_i = n + 1 pi+qi=n+1
  2. 对于任意 1 ≤ i ≤ n 1 \leq i \leq n 1in,都有 ∣ p i − q i ∣ = a i |p_i - q_i| = a_i piqi=ai

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

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

输入格式

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

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

输出格式

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

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

样例输入

3
2 2 0

样例输出

1 3 2
3 1 2

数据范围

1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1n105
0 ≤ a i ≤ n − 1 0 \leq a_i \leq n-1 0ain1

题解

根据题目条件,可以得到 p i p_i pi q i q_i qi 的关系:

  1. p i + q i = n + 1 p_i + q_i = n + 1 pi+qi=n+1
  2. ∣ p i − q i ∣ = a i |p_i - q_i| = a_i piqi=ai

由条件 1 可知, p i p_i pi q i q_i qi 的和是固定的,都等于 n + 1 n+1 n+1。因此,可以预处理出所有可能的 ( p i , q i ) (p_i, q_i) (pi,qi) 对,并按照 ∣ p i − q i ∣ |p_i - q_i| piqi 的值进行分组。

接下来,将输入的数组 a a a 排序,然后与预处理得到的 ∣ p i − q i ∣ |p_i - q_i| piqi 的值进行比较。如果两个数组排序后不相同,说明无解,直接输出 − 1 -1 1

如果两个数组排序后相同,则按照 a a a 数组的顺序,依次从对应的 ( p i , q i ) (p_i, q_i) (pi,qi) 分组中取出一对值,即可得到满足条件的排列 p p p q q q

时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),空间复杂度为 O ( n ) O(n) O(n)

参考代码

  • 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];
        }
        
        int[] c = new int[n];
        Map<Integer, List<int[]>> mp = new HashMap<>();
        for (int i = 0; i < n; i++) {
            c[i] = Math.abs(i - (n - 1 - i));
            mp.computeIfAbsent(c[i], k -> new ArrayList<>()).add(new int[]{i, n - 1 - i});
        }
        
        Arrays.sort(b);
        Arrays.sort(c);
        
        if (!Arrays.equals(b, c)) {
            System.out.println(-1);
        } else {
            int[] p = new int[n];
            int[] q = new int[n];
            for (int i = 0; i < n; i++) {
                int[] pair = mp.get(a[i]).remove(mp.get(a[i]).size() - 1);
                p[i] = pair[0] + 1;
                q[i] = pair[1] + 1;
            }
            for (int i = 0; i < n; i++) {
                System.out.print(p[i] + " ");
            }
            System.out.println();
            for (int i = 0; i < n; i++) {
                System.out.print(q[i] + " ");
            }
        }
    }
}
  • Cpp
#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    auto b = a;
    vector<int> c(n);
    unordered_map<int, vector<pair<int, int>>> mp;
    for (int i = 0; i < n; i++) {
        c[i] = abs(i - (n - 1 - i));
        mp[c[i]].push_back({i, n - 1 - i});
    }
    
    sort(b.begin(), b.end());
    sort(c.begin(), c.end());
    
    if (b != c) {
        cout << -1 << endl;
    } else {
        vector<int> p(n), q(n);
        for (int i = 0; i < n; i++) {
            auto pair = mp[a[i]].back();
            mp[a[i]].pop_back();
            p[i] = pair.first + 1;
            q[i] = pair.second + 1;
        }
        for (int i = 0; i < n; i++) {
            cout << p[i] << ' ';
        }
        cout << endl;
        for (int i = 0; i < n; i++) {
            cout << q[i] << ' ';
        }
    }
    
    return 0;
}

💝 03.K小姐的森林管理

题目描述

K小姐是一位热爱大自然的女孩,她拥有一片由 n n n 棵树组成的森林。这片森林可以看作一个无向图,树木之间通过 m m m 条小路相连。

为了更好地管理这片森林,K小姐可以进行以下两种操作:

  1. 在任意一棵现有的树上种植一棵新的小树苗,并用一条小路将其与原来的树相连。
  2. 移除一棵叶子节点(即度数为1的节点)以及与之相连的小路。

K小姐的目标是使森林中的每个连通块(即互相连通的树木集合)包含相同数量的树木。你的任务是帮助K小姐计算出达成目标状态所需的最少操作次数。

输入格式

第一行包含两个正整数 n n n m m m,分别表示森林中树木的数量和小路的数量。

接下来 m m m 行,每行包含两个正整数 u u u v v v,表示编号为 u u u v v v 的两棵树之间有一条小路相连。

输出格式

输出一个整数,表示K小姐达成目标状态所需的最少操作次数。

样例输入

4 2
1 2
1 3

样例输出

2

数据范围

1 ≤ m < n ≤ 1 0 5 1 \le m < n \le 10^5 1m<n105

保证给定的无向图是一个森林。

题解

本题可以通过并查集和前缀和的思想来解决。

首先,我们可以使用并查集来处理出森林中每个连通块的大小。这样就将问题转化为了使数组中所有元素相等的最小代价问题。

接下来,我们可以对表示连通块大小的数组进行排序,然后用前缀和计算出前 i i i 个元素的和。这样就可以在 O ( c n t ) O(cnt) O(cnt) 的时间复杂度内(其中 c n t cnt cnt 为连通块的个数)计算出将所有连通块的大小变为 x x x 的代价。

最后,我们遍历所有可能的连通块大小 x x x,就能得到最小的操作次数。

总时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn)

参考代码

  • Python
def find(x):
    if p[x] != x:
        p[x] = find(p[x])
    return p[x]

n, m = map(int, input().split())
p = list(range(n + 1))
num = [1] * (n + 1)

for _ in range(m):
    a, b = map(int, input().split())
    px, py = find(a), find(b)
    if px != py:
        p[px] = py
        num[py] += num[px]

c = [num[i] for i in range(1, n + 1) if p[i] == i]
cnt = len(c)
c.sort()

sum = [0] * cnt
for i in range(cnt):
    sum[i] = c[i]
    if i > 0:
        sum[i] += sum[i - 1]

res = n
for i in range(cnt):
    res = min(res, (i + 1) * c[i] - sum[i] + sum[cnt - 1] - sum[i] - (cnt - i - 1) * c[i])

print(res)
  • Java
import java.util.*;

public class Main {
    static int[] p, num, c, sum;
    
    static int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        p = new int[n + 1];
        num = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            p[i] = i;
            num[i] = 1;
        }
        
        for (int i = 0; i < m; i++) {
            int a = sc.nextInt(), b = sc.nextInt();
            int px = find(a), py = find(b);
            if (px != py) {
                p[px] = py;
                num[py] += num[px];
            }
        }
        
        int cnt = 0;
        for (int i = 1; i <= n; i++) {
            if (p[i] == i) cnt++;
        }
        c = new int[cnt];
        sum = new int[cnt];
        cnt = 0;
        for (int i = 1; i <= n; i++) {
            if (p[i] == i) c[cnt++] = num[i];
        }
        Arrays.sort(c);
        
        for (int i = 0; i < cnt; i++) {
            sum[i] = c[i];
            if (i > 0) sum[i] += sum[i - 1];
        }
        
        int res = n;
        for (int i = 0; i < cnt; i++) {
            res = Math.min(res, (i + 1) * c[i] - sum[i] + sum[cnt - 1] - sum[i] - (cnt - i - 1) * c[i]);
        }
        System.out.println(res);
    }
}
  • Cpp
#include <iostream>
#include <algorithm>

using namespace std;
const int N = 1e5 + 7;

int n, m, p[N], num[N], c[N], sum[N];

int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        p[i] = i;
        num[i] = 1;
    }
    
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        int px = find(a), py = find(b);
        if (px != py) {
            p[px] = py;
            num[py] += num[px];
        }
    }
    
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (p[i] == i) c[cnt++] = num[i];
    }
    sort(c, c + cnt);
    
    for (int i = 0; i < cnt; i++) {
        sum[i] = c[i];
        if (i > 0) sum[i] += sum[i - 1];
    }
    
    int res = n;
    for (int i = 0; i < cnt; i++) {
        res = min(res, (i + 1) * c[i] - sum[i] + sum[cnt - 1] - sum[i] - (cnt - i - 1) * c[i]);
    }
    cout << res << endl;
    
    return 0;
}

写在最后

📧 清隆这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 清隆领取,会在飞书进行同步的跟新。

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1631240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3. uniapp开发工具的一些事

前言 新的一天&#xff0c;又要开始卷起来了&#xff0c;开发程序开发当前离不开开发工具&#xff0c;一个好的开发工具办事起来那必然是事倍功半的...本文主要分享了关于uniapp里开发工具的一些事~ 概述 阅读时间&#xff1a;约5&#xff5e;7分钟&#xff1b; 本文重点&am…

《深入理解mybatis原理》 MyBatis的架构设计以及实例分析

《深入理解mybatis原理》 MyBatis的架构设计以及实例分析 MyBatis是目前非常流行的ORM框架&#xff0c;它的功能很强大&#xff0c;然而其实现却比较简单、优雅。本文主要讲述MyBatis的架构设计思路&#xff0c;并且讨论MyBatis的几个核心部件&#xff0c;然后结合一个select查…

linux下安装deepspeed

安装步骤 一开始安装deepspeed不可以使用pip直接进行安装。 这时我们需要利用git进行clone下载到本地&#xff1a; git clone https://github.com/microsoft/DeepSpeed.git 进入到deepspeed的安装目录下 cd /home/bingxing2/ailab/group/ai4agr/wzf/Tools/DeepSpeed 激活…

探索小猪APP分发平台:数字时代的新宠

随着数字化进程的加速&#xff0c;移动应用&#xff08;APP&#xff09;市场正迅速扩大。在这个充满竞争的市场中&#xff0c;一个优秀的APP分发平台能够帮助开发者和商家更有效地触及潜在用户&#xff0c;而小猪APP分发平台&#xff08;www.ppzhu.net&#xff09;正是其中的佼…

Windows 下安装RabbitMQ

一、消息中间件 ActiveMQ&#xff1a;基于JMS RabbitMQ&#xff1a;基于AMQP协议&#xff0c;erlang语言开发&#xff0c;稳定性好 RocketMQ&#xff1a;基于JMS&#xff0c;阿里巴巴产品&#xff0c;目前交由Apache基金会 Kafka&#xff1a;分布式消息系统&#xff0c;高吞吐…

tableau如何传参数到MySQL数据库

1、打开tableau连接本地MySQL-》新建自定义sql-》创建参数 2、新建一个简单的工作表-》把维度拖拽到行显示结果-》右键显示参数 3、参数传递到数据库sql写法 select * from yonghu where yonghu.姓名 like concat(%,<参数.姓名>,%)select * FROMabadata4WHERE abadata4…

华为认证云计算方向,真的值得学吗……

在数字化转型的浪潮中&#xff0c;云计算技术正变得越来越关键。 华为&#xff0c;作为全球领先的信息与通信技术&#xff08;ICT&#xff09;解决方案提供商&#xff0c;其提供的云计算认证被广泛认为是行业内的重要资质之一。 那么&#xff0c;华为云计算认证的价值何在&am…

【PyTorch与深度学习】2、PyTorch张量的运算API(上)

课程地址 最近做实验发现自己还是基础框架上掌握得不好&#xff0c;于是开始重学一遍PyTorch框架&#xff0c;这个是课程笔记&#xff0c;这个课还是讲的简略&#xff0c;我半小时的课听了一个半小时。 1. 张量 1.1 张量操作 &#xff08;1&#xff09;chunk&#xff1a;将一…

1.Neo4j图数据库介绍

背景 1.社交、电商、金融、零售、物联网行业&#xff0c;现实社会组织起了一张庞大复杂的关系网。 2.传统数据库很难处理关系运算。 3.需要一种支持海量复杂数据关系运算的数据库。 图数据库是以图数据结构存储和查询数据&#xff0c;是一种NoSQL数据库&#xff0c;存储更多…

冯唐成事心法笔记 —— 知己

系列文章目录 冯唐成事心法笔记 —— 知己 冯唐成事心法笔记 —— 知人 冯唐成事心法笔记 —— 知世 冯唐成事心法笔记 —— 知智慧 文章目录 系列文章目录卷首语 管理是一生的日常&#xff0c;成事是一生的修行PART 1 知己 用好自己的天赋如何管理自我第一&#xff0c;如何…

沉浸式翻译 chrome 插件 Immersive Translate - Translate Website PDF

免费翻译网站&#xff0c;翻译PDF和Epub电子书&#xff0c;双语翻译视频字幕 &#x1f4e3; 网络上口碑爆炸的网站翻译扩展工具【沉浸式翻译】⭐⭐⭐⭐⭐ &#x1f4bb; 功能特点如下&#xff1a; &#x1f4f0; 网站翻译 &#x1f680; 提供双语网站翻译&#xff0c;智能识…

数据库常考理论

1 笛卡尔积X与自然连接∞的区别 2 求候选键 3 无损连接及函数依赖 4 范式判断 笛卡尔积&#xff1a;S1*S2,产生的结果包括S1和S2的所有属性列&#xff0c;并且S1中每条记录依次和S2中所有记录 组合成一条记录&#xff0c;最终属性列为S1S2属性列&#xff0c;记录数为S1*S2记…

k8s pod使用sriov

之前的文章中讲了k8s multus的使用&#xff0c;本章节来讲述下如何使用multus来实现sriov的使用。 一、sriov 简介 SR-IOV在2010年左右由Intel提出&#xff0c;但是随着容器技术的推广&#xff0c;intel官方也给出了SR-IOV技术在容器中使用的开源组件&#xff0c;例如&#…

Java集合框架-Collection-queue

目录 一、Deque二、ArrayDequeArrayDeque层次结构图ArrayDeque概述ArrayDeque底层数据结构ArrayDeque常用方法(简略) 三、PriorityQueuePriorityQueue层次结构图PriorityQueue概述PriorityQueue 底层数据结构PriorityQueue常用方法(详细) Java里有一个叫做Stack的类&#xff0c…

Qt | 标准、复选、单选、工具、命令按钮大全

01、QPushButton QPushButton 类(标准按钮) 示例 3:默认按钮与自动默认按钮 02、QCheckBox QCheckBox 类(复选按钮) 1、复选按钮的第三状态(见右图 Qt5.10.1 的选中状态):是指除了选中 和未选中状态之外的第三种状态,这种状态用来指示“不变”,表 示用户既不选中也不取…

go语言实现简单认证样例

目录 1、代码实现样例 2、postman调用 1、代码实现样例 package mainimport ("net/http""strings""github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin" )var (// 密钥&#xff0c;用于验证 JWT 令牌signingKey []byte("…

09 配置文件日志多线程

配置文件 配置文件 在企业开发过程中&#xff0c;我们习惯把一些需要灵活配置的数据放在一些文本文件中&#xff0c;而不是在Java代码写死我们把这种存放程序配置信息的文件&#xff0c;统称为配置文件 配置文件一般要求有明确的格式&#xff0c;以方便读写操作!!! Properti…

【已解决】VMware虚拟机中出现无法将“iso文件”当做CD-ROM映像进行连接:找不到该文件的错误

报错 在VMware上运行虚拟机时报错&#xff1a;VMware虚拟机中出现无法将“iso文件”当做CD-ROM映像进行连接&#xff1a;找不到该文件的错误 原因分析 找不到这个iso文件了&#xff0c;检查文件位置 解决方案 找到iso文件&#xff0c;然后在VM中编辑虚拟机中这个文件的位置…

双塔模型在召回和粗排的区别

答案参考&#xff1a;推荐系统中&#xff0c;双塔模型用于粗排和用于召回的区别有哪些? - 知乎 召回和粗排在不同阶段面临样本不一样&#xff0c;对双塔来说样本分布差异会使召回和粗排采取不一样的方式。召回打分空间是全部item空间&#xff0c;曝光只有很少一部分&#xff0…