校招算法笔面试 | 校招笔面试真题-年会抢玩偶游戏

题目## 题目## 题目

题目链接

解题思路

这是一道数学推导题目。根据题目规则:

  1. N N N 个人排成一排,共有 M M M 个玩偶
  2. 每个人抢到的玩偶不能比左右两边的人多两个或以上
  3. K K K 个位置的人想要赢得游戏

求解步骤:

  1. 假设第 K K K 个位置的人抢到 x x x 个玩偶
  2. 根据规则,相邻位置的人最少要抢到 x − 1 x-1 x1 个玩偶
  3. 往两边递推,每个位置最少要抢到的玩偶数量会依次减1
  4. 通过数学推导得出最优解公式: x = 2 × M + 2 × k 2 − 2 × k − 2 × k × N + N 2 + N 2 × N x = \frac{2\times M + 2\times k^2 - 2\times k - 2\times k\times N + N^2 + N}{2\times N} x=2×N2×M+2×k22×k2×k×N+N2+N

代码

#include <iostream>
using namespace std;

int main() {
    int N, M, k;
    cin >> N >> M >> k;
    
    // 输入验证
    if (N <= 0 || M <= 0 || k <= 0) {
        cout << 0;
        return 0;
    }
    
    // 计算最优解
    int x = (2*M + 2*k*k - 2*k - 2*k*N + N*N + N) / (2*N);
    
    // 验证结果是否有效
    if (x < 0 || x > M) {
        cout << 0;
    } else {
        cout << x;
    }
    return 0;
}
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();
        int k = sc.nextInt();
        
        if (N <= 0 || M <= 0 || k <= 0) {
            System.out.println(0);
            return;
        }
        
        int x = (2*M + 2*k*k - 2*k - 2*k*N + N*N + N) / (2*N);
        
        if (x < 0 || x > M) {
            System.out.println(0);
        } else {
            System.out.println(x);
        }
    }
}
def solve(N: int, M: int, k: int) -> int:
    if N <= 0 or M <= 0 or k <= 0:
        return 0
    
    x = (2*M + 2*k*k - 2*k - 2*k*N + N*N + N) // (2*N)
    
    return x if 0 <= x <= M else 0

N, M, k = map(int, input().split())
print(solve(N, M, k))

算法及复杂度

  • 算法:数学推导
  • 时间复杂度: O ( 1 ) \mathcal{O}(1) O(1) - 只需要进行简单的数学计算
  • 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1) - 只使用了常数级别的额外空间

题目链接

题解

题目难度:中等

知识点:LCS(最长公共子序列问题),动态规划

分析:

本题实际是要找出s的最长子序列,看到这个问题就应该想到利用动态规划去解决。一般是找s1、s2两个字符串中的最长子序列,那么该题中就可以遍历s,以每个字符位置作为分割点,将s分割成s1和s2两个字符串,利用动态规划去求解s1和s2中的最长子序列,结果存储在dp[i][j]的二维数组中。对于dp数组,下标从1开始对应字符串中的0下标对应的字符。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
通过上面一个dp数组表,就可以算出最长子序列长度为3



import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		int len = s.length();
		int res = 0;
		for(int i = 0; i

[题目链接](https://www.nowcoder.com/practice/3745638815d04c26babcfc463c25478c?tpId=182&tqId=25947&sourceUrl=/exam/oj&channelPut=wcsdn&fromPut=wcsdn)

## 解题思路

这是一道数学计算问题,主要思路如下:

1. 问题分析:
   - 已知公司总人数 $W$,当前平均年龄 $Y$
   - 每年离职率 $x$,新员工年龄 $21$ 岁
   - 需要计算 $N$ 年后的平均年龄

2. 解决方案:
   - 每年的平均年龄计算公式:
     - 留任员工:$(1-x)(Y+1)$
     - 新入职员工:$x*21$
   - 最终年龄 = 留任员工年龄 + 新员工年龄
   - 迭代 $N$ 次得到最终结果

3. 关键点:
   - 每年都要更新平均年龄 $Y$
   - 结果需要向上取整
   - 注意浮点数精度

---

## 代码

```cpp []
#include <iostream>
#include <cmath>
using namespace std;

// 计算一年后的平均年龄
float calculateNextYear(float currentAge, double leaveRate) {
    // 留任员工年龄增长1岁
    float stayEmployees = (1 - leaveRate) * (currentAge + 1);
    // 新员工固定21岁
    float newEmployees = leaveRate * 21;
    // 返回新的平均年龄
    return stayEmployees + newEmployees;
}

int main() {
    int W, N;
    float Y, x;
    
    while (cin >> W >> Y >> x >> N) {
        float averageAge = Y;
        // 模拟N年
        for (int i = 0; i < N; i++) {
            averageAge = calculateNextYear(averageAge, x);
        }
        // 向上取整并输出
        cout << ceil(averageAge) << endl;
    }
    return 0;
}
import java.util.*;

public class Main {
    // 计算一年后的平均年龄
    private static float calculateNextYear(float currentAge, double leaveRate) {
        // 留任员工年龄增长1岁
        float stayEmployees = (float)((1 - leaveRate) * (currentAge + 1));
        // 新员工固定21岁
        float newEmployees = (float)(leaveRate * 21);
        // 返回新的平均年龄
        return stayEmployees + newEmployees;
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        while (sc.hasNext()) {
            int W = sc.nextInt();
            float Y = sc.nextFloat();
            float x = sc.nextFloat();
            int N = sc.nextInt();
            
            float averageAge = Y;
            // 模拟N年
            for (int i = 0; i < N; i++) {
                averageAge = calculateNextYear(averageAge, x);
            }
            // 向上取整并输出
            System.out.println((int)Math.ceil(averageAge));
        }
    }
}
import math

def calculate_next_year(current_age: float, leave_rate: float) -> float:
    # 留任员工年龄增长1岁
    stay_employees = (1 - leave_rate) * (current_age + 1)
    # 新员工固定21岁
    new_employees = leave_rate * 21
    # 返回新的平均年龄
    return stay_employees + new_employees

while True:
    try:
        # 读取输入
        W, Y, x, N = map(float, input().split())
        N = int(N)  # N需要是整数
        
        average_age = Y
        # 模拟N年
        for _ in range(N):
            average_age = calculate_next_year(average_age, x)
        
        # 向上取整并输出
        print(math.ceil(average_age))
    except EOFError:
        break

算法及复杂度

  • 算法:数学模拟
  • 时间复杂度: O ( N ) \mathcal{O}(N) O(N) - N N N 为需要模拟的年数
  • 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1) - 只需要常数额外空间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值