【蚂蚁笔试题汇总】2024-04-13-蚂蚁春招笔试题-三语言题解(CPP/Python/Java)

🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员

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

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

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

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

🧸 01.购物优惠

题目描述

K小姐来到了一家超市购物,超市里有 n n n 种商品,每种商品只能购买一件。其中有些商品支持优惠活动,如果用支付宝付款可以享受 95 95 95 折优惠,有些商品则不支持优惠。K小姐的支付宝余额为 m m m 元,她想知道最多能买几件商品。

输入格式

第一行包含两个正整数 n n n m m m,分别表示商品的种类数和支付宝余额。

第二行包含 n n n 个正整数,表示每种商品的价格。

第三行包含一个长度为 n n n 的字符串,仅由 0 0 0 1 1 1 组成。若第 i i i 个字符为 1 1 1,则表示第 i i i 种商品支持优惠;否则表示不支持优惠。

输出格式

输出一个整数,表示最多能购买的商品数量。

样例输入

3 975
1000 500 500
0 0 1

样例输出

2

数据范围

  • 1 ≤ n ≤ 100 1 \leq n \leq 100 1n100
  • 1 ≤ m ≤ 1 0 5 1 \leq m \leq 10^5 1m105
  • 商品价格均为正整数,且不超过 1 0 4 10^4 104

题解

可以先将所有商品的价格乘以相应的折扣(支持优惠的乘以 0.95 0.95 0.95,不支持的乘以 1 1 1),然后将商品按照价格从小到大排序。接下来,从价格最小的商品开始,依次购买,直到无法再购买为止。最后购买的商品数量即为答案。

具体步骤如下:

  1. 读入 n n n, m m m 以及 n n n 个商品的价格和优惠信息。
  2. 根据优惠信息,将支持优惠的商品价格乘以 0.95 0.95 0.95
  3. 将所有商品按照价格从小到大排序。
  4. 初始化答案 a n s = 0 ans = 0 ans=0,当前花费 s u m = 0 sum = 0 sum=0
  5. 从价格最小的商品开始,依次尝试购买:
    • 如果当前花费加上该商品的价格不超过 m m m,则购买该商品,将答案 a n s ans ans 1 1 1,当前花费 s u m sum sum 加上该商品价格。
    • 否则,无法再购买,退出循环。
  6. 输出答案 a n s ans ans

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

参考代码

  • Python
n, m = map(int, input().split())
prices = list(map(int, input().split()))
discounts = input()

for i in range(n):
    if discounts[i] == '1':
        prices[i] *= 0.95

prices.sort()
ans = total = 0
for price in prices:
    total += price
    if total <= m:
        ans += 1
    else:
        break

print(ans)
  • Java
import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        double[] prices = new double[n];
        for (int i = 0; i < n; i++) {
            prices[i] = sc.nextDouble();
        }
        String discounts = sc.next();
        
        for (int i = 0; i < n; i++) {
            if (discounts.charAt(i) == '1') {
                prices[i] *= 0.95;
            }
        }
        
        Arrays.sort(prices);
        int ans = 0;
        double total = 0;
        for (double price : prices) {
            total += price;
            if (total <= m) {
                ans++;
            } else {
                break;
            }
        }
        
        System.out.println(ans);
    }
}
  • Cpp
#include <iostream>
#include <algorithm>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    double prices[n];
    for (int i = 0; i < n; i++) {
        cin >> prices[i];
    }
    string discounts;
    cin >> discounts;
    
    for (int i = 0; i < n; i++) {
        if (discounts[i] == '1') {
            prices[i] *= 0.95;
        }
    }
    
    sort(prices, prices + n);
    int ans = 0;
    double total = 0;
    for (double price : prices) {
        total += price;
        if (total <= m) {
            ans++;
        } else {
            break;
        }
    }
    
    cout << ans << endl;
    return 0;
}

🎁 02.字母识别

题目描述

LYA 正在开发一个字母识别系统。现在她得到了一些由 '.''*' 组成的矩阵图案,希望你帮忙识别图案中 '*' 字符表示的是字母 'L' 还是 'T'。注意,图案可能会被旋转或翻转。

输入格式

第一行输入一个正整数 T T T,表示询问的组数。

对于每组询问:

  • 第一行输入两个正整数 n n n m m m,分别表示图案矩阵的行数和列数。
  • 接下来 n n n 行,每行输入一个长度为 m m m 的、仅包含 '.''*' 的字符串,表示图案矩阵。

保证字母宽度为 1 1 1,且每一笔都是水平或垂直的。

输出格式

输出 T T T 行,对于每组询问,如果答案是 'L' 则输出 "L",如果是 'T' 则输出 "T"

样例输入

2
4 4
....
..*.
..*.
***.
5 6
..*...
..*...
..*...
******
......

样例输出

L
T

数据范围

  • 1 ≤ T ≤ 100 1 \leq T \leq 100 1T100
  • 1 ≤ n , m ≤ 100 1 \leq n, m \leq 100 1n,m100

题解

本题可以通过观察字母 'L''T' 的特点来判断。

对于字母 'L',每个 '*' 格子最多与其他两个 '*' 格子相邻。而对于字母 'T',必定存在一个 '*' 格子与其他三个 '*' 格子相邻。

因此,可以遍历矩阵中的每个 '*' 格子,统计其相邻的 '*' 格子数量。如果存在一个格子相邻的 '*' 格子数量大于等于 3 3 3,则说明这是一个 'T',否则就是 'L'

具体步骤如下:

  1. 读入询问组数 T T T
  2. 对于每组询问:
    • 读入矩阵的行数 n n n 和列数 m m m,以及 n n n 行矩阵。
    • 初始化标记变量 f l a g flag flag f a l s e false false
    • 遍历矩阵中的每个格子 ( i , j ) (i, j) (i,j):
      • 如果当前格子为 '*',则统计其上下左右四个相邻格子中 '*' 的数量 c n t cnt cnt
      • 如果 c n t ≥ 3 cnt \geq 3 cnt3,则将 f l a g flag flag 置为 t r u e true true
    • 如果 f l a g flag flag t r u e true true,则输出 "T",否则输出 "L"

时间复杂度 O ( T × n × m ) O(T \times n \times m) O(T×n×m),空间复杂度 O ( n × m ) O(n \times m) O(n×m)

参考代码

  • Python
T = int(input())
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

for _ in range(T):
    n, m = map(int, input().split())
    grid = [input() for _ in range(n)]
    
    flag = False
    for i in range(n):
        for j in range(m):
            if grid[i][j] == '*':
                cnt = sum(1 for k in range(4) if 0 <= i + dx[k] < n and 0 <= j + dy[k] < m and grid[i + dx[k]][j + dy[k]] == '*')
                if cnt >= 3:
                    flag = True
    
    print("T" if flag else "L")
  • Java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        int[] dx = {-1, 0, 1, 0};
        int[] dy = {0, 1, 0, -1};
        
        while (T-- > 0) {
            int n = sc.nextInt();
            int m = sc.nextInt();
            char[][] grid = new char[n][m];
            for (int i = 0; i < n; i++) {
                grid[i] = sc.next().toCharArray();
            }
            
            boolean flag = false;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (grid[i][j] == '*') {
                        int cnt = 0;
                        for (int k = 0; k < 4; k++) {
                            int x = i + dx[k], y = j + dy[k];
                            if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == '*') {
                                cnt++;
                            }
                        }
                        if (cnt >= 3) {
                            flag = true;
                        }
                    }
                }
            }
            
            System.out.println(flag ? "T" : "L");
        }
    }
}
  • Cpp
#include <iostream>
using namespace std;

const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};

int main() {
    int T;
    cin >> T;
    
    while (T--) {
        int n, m;
        cin >> n >> m;
        char grid[n][m];
        for (int i = 0; i < n; i++) {
            cin >> grid[i];
        }
        
        bool flag = false;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == '*') {
                    int cnt = 0;
                    for (int k = 0; k < 4; k++) {
                        int x = i + dx[k], y = j + dy[k];
                        if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == '*') {
                            cnt++;
                        }
                    }
                    if (cnt >= 3) {
                        flag = true;
                    }
                }
            }
        }
        
        cout << (flag ? "T" : "L") << endl;
    }
    
    return 0;
}

🎉 03.最大公约数之旅

问题描述

K小姐计划进行一次旅行。她有一个长度为 n n n 的整数数组,表示她每天的旅行预算。在旅行开始之前,她可以将这个数组按任意顺序重新排列。

接下来,K小姐需要将数组分成两个非空的部分,使得这两部分的元素和的最大公约数最大。她想知道这个最大的最大公约数是多少。

输入格式

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

第二行包含 n n n 个以空格分隔的正整数,表示数组中的元素。

输出格式

输出一个整数,表示两部分元素和的最大公约数的最大值。

样例输入

3
1 2 3

样例输出

3

数据范围

1 ≤ n ≤ 100 1 \leq n \leq 100 1n100
1 ≤ a i ≤ 100 1 \leq a_i \leq 100 1ai100

题解

本题可以使用动态规划来解决。可以先求出数组元素的总和 s u m sum sum,然后定义一个布尔型数组 d p dp dp,其中 d p [ i ] dp[i] dp[i] 表示是否可以从数组中选出一些元素,使得它们的和等于 i i i

初始时, d p = t r u e dp=true dp=true,因为可以不选任何元素。接下来,遍历数组中的每个元素 a a a,对于每个 j j j s u m sum sum a a a 递减,如果 d p [ j − a ] dp[j-a] dp[ja] t r u e true true,则将 d p [ j ] dp[j] dp[j] 更新为 t r u e true true。这样做的目的是,如果可以选出一些元素使得它们的和等于 j − a j-a ja,那么再加上当前元素 a a a,就可以得到和为 j j j 的一种方案。

最后,遍历 d p dp dp 数组,对于每个为 t r u e true true d p [ i ] dp[i] dp[i],将数组分成两部分,一部分的元素和为 i i i,另一部分的元素和为 s u m − i sum-i sumi。我们计算这两部分元素和的最大公约数,并更新答案。

时间复杂度为 O ( n × s u m ) O(n \times sum) O(n×sum),空间复杂度为 O ( s u m ) O(sum) O(sum)

参考代码

  • Python
def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)

n = int(input())
arr = list(map(int, input().split()))

total = sum(arr)
dp = [False] * (total + 1)
dp[0] = True

for num in arr:
    for j in range(total, num - 1, -1):
        dp[j] |= dp[j - num]

ans = 0
for i in range(1, total):
    if dp[i]:
        left = i
        right = total - i
        if left and right:
            ans = max(ans, gcd(left, right))

print(ans)
  • Java
import java.util.Scanner;

public class Main {
    public static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

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

        boolean[] dp = new boolean[total + 1];
        dp[0] = true;

        for (int num : arr) {
            for (int j = total; j >= num; j--) {
                dp[j] |= dp[j - num];
            }
        }

        int ans = 0;
        for (int i = 1; i < total; i++) {
            if (dp[i]) {
                int left = i;
                int right = total - i;
                if (left != 0 && right != 0) {
                    ans = Math.max(ans, gcd(left, right));
                }
            }
        }

        System.out.println(ans);
    }
}
  • Cpp
#include <iostream>
#include <vector>
using namespace std;

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

int main() {
    int n;
    cin >> n;
    vector<int> arr(n);
    int total = 0;
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
        total += arr[i];
    }

    vector<bool> dp(total + 1, false);
    dp[0] = true;

    for (int num : arr) {
        for (int j = total; j >= num; j--) {
            dp[j] |= dp[j - num];
        }
    }

    int ans = 0;
    for (int i = 1; i < total; i++) {
        if (dp[i]) {
            int left = i;
            int right = total - i;
            if (left && right) {
                ans = max(ans, gcd(left, right));
            }
        }
    }

    cout << ans << endl;
    return 0;
}

写在最后

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

在这里插入图片描述

在这里插入图片描述

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
2023年3月11日,美团春季招聘笔试中共包含五道编程题目。以下是对每道题目的简要说明: 1. 题目一:这道题目要求解决一个数字统计的问题。可能涉及到的知识点包括数据结构、循环和条件判断等。解决问题的思路可能是使用字典等数据结构来保存统计结果,并使用循环逐个读取输入数据并进行统计。 2. 题目二:这道题目可能是一个字符串处理的问题。需要使用字符串的方法进行操作,如提取、拼接、查找和替换等。可能的解决思路包括使用正则表达式、切片和遍历等。 3. 题目:这道题目可能涉及到算法和数据结构的知识。可能是一道涉及到数组、链表、树等数据结构的问题。解决思路可能包括遍历、递归、搜索和排序等。 4. 题目四:这道题目可能是一个动态规划的问题。需要根据给定的条件和规则,通过动态规划的方式求解问题。解决思路包括定义状态和转移方程,使用递推或记忆化搜索进行求解。 5. 题目五:这道题目可能是一个图论或网络问题。需要根据给定的图或网络结构,解决一个相关的问题。可能涉及到广度优先搜索、深度优先搜索、最短路径等知识。解决思路可能包括使用图或网络的相关算法进行求解。 以上只是对这五道编程题目的一些可能情况进行的简要描述,具体的题目内容可能会有所不同。希望这些信息能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值