青训营试题算法解析八

144 阅读7分钟

试题1:小F的矩阵调整

问题描述: 小F得到了一个矩阵。如果矩阵中某一个格子的值是偶数,则该值变为它的三倍;如果是奇数,则保持不变。小F想知道调整后的矩阵是什么样子的

#include <vector>
#include <iostream>
using namespace std;

vector<vector<int>> solution(vector<vector<int>> a) {
    // 遍历矩阵中的每一个元素
    for (int i = 0; i < a.size(); ++i) {
        for (int j = 0; j < a[i].size(); ++j) {
            // 检查元素的奇偶性
            if (a[i][j] % 2 == 0) {
                // 如果是偶数,将其值变为原来的三倍
                a[i][j] *= 3;
            }
            // 如果是奇数,保持不变(这里不需要额外操作)
        }
    }
    // 返回更新后的矩阵
    return a;
}

int main() {
    cout << (solution({{1, 2, 3}, {4, 5, 6}}) == vector<vector<int>>{{1, 6, 3}, {12, 5, 18}}) << endl;
    cout << (solution({{7, 8, 9}, {10, 11, 12}}) == vector<vector<int>>{{7, 24, 9}, {30, 11, 36}}) << endl;
    cout << (solution({{2, 4}, {6, 8}}) == vector<vector<int>>{{6, 12}, {18, 24}}) << endl;
    return 0;
}

试题2:小Q的非素数和排列问题

问题描述: 小C对排列很感兴趣,她想知道有多少个长度为n的排列满足任意两个相邻元素之和都不是素数。排列定义为一个长度为n的数组,其中包含从1到n的所有整数,每个数字恰好出现一次。

#include <iostream>
#include <vector>
#include <algorithm>


bool isPrime(int num) {
    if (num <= 1) return false;
    for (int i = 2; i * i <= num; ++i) {
        if (num % i == 0) return false;
    }
    return true;
}

bool isValidPermutation(const std::vector<int>& perm) {
    for (size_t i = 0; i < perm.size() - 1; ++i) {
        if (isPrime(perm[i] + perm[i + 1])) {
            return false;
        }
    }
    return true;
}

int solution(int n) {
    std::vector<int> perm(n);
    for (int i = 0; i < n; ++i) {
        perm[i] = i + 1;
    }
    
    int count = 0;
    do {
        if (isValidPermutation(perm)) {
            count++;
        }
    } while (std::next_permutation(perm.begin(), perm.end()));
    
    return count;
}

int main() {
    std::cout << (solution(5) == 4) << std::endl;
    std::cout << (solution(3) == 0) << std::endl;
    std::cout << (solution(6) == 24) << std::endl;
}

试题3:数字字符串中圆圈的数量计算

问题描述: 小I拿到了一串数字字符,她想知道这串数字中一共有多少个圆圈。具体规则如下:

数字0、6、9各含有一个圆圈。 数字8含有两个圆圈。 其他数字不含有任何圆圈。

#include <iostream>
#include <string>

int solution(const std::string& s) {
    int circleCount[10] = {1, 0, 0, 0, 0, 0, 1, 0, 2, 1};
    int totalCircles = 0;
    for (char c : s) {
        totalCircles += circleCount[c - '0'];
    }
    
    return totalCircles;
}

int main() {
    std::cout << (solution("1234567890") == 5) << std::endl;
    std::cout << (solution("8690") == 5) << std::endl;
    std::cout << (solution("1111") == 0) << std::endl;
}

试题4:徒步旅行中的补给问题

问题描述: 小R正在计划一次从地点A到地点B的徒步旅行,总路程需要 N 天。为了在旅途中保持充足的能量,小R每天必须消耗1份食物。幸运的是,小R在路途中每天都会经过一个补给站,可以购买食物进行补充。然而,每个补给站的食物每份的价格可能不同,并且小R最多只能同时携带 K 份食物。

现在,小R希望在保证每天都有食物的前提下,以最小的花费完成这次徒步旅行。你能帮助小R计算出最低的花费是多少吗?

def solution(m: int, s: str) -> int:
    # write code here
    n = len(s)
    dp = [[-1] * (m + 1) for _ in range(n + 1)]  
    dp[0][0] = 0 
 

    match_info = [[] for _ in range(n)] 
    for i in range(n):
        max_len = min(n - i, 3 + m) 
        dp_match = [[float('inf')] * (max_len + 1) for _ in range(4)] 
        dp_match[0][0] = 0
        for p in range(4): 
            for q in range(max_len + 1):  
                if dp_match[p][q] > m:  
                    continue
                if p < 3 and q < max_len:  
                    cost = 0 if s[i + q] == 'UCC'[p] else 1
                    dp_match[p + 1][q + 1] = min(dp_match[p + 1][q + 1], dp_match[p][q] + cost)
                if p < 3:  # 插入
                    dp_match[p + 1][q] = min(dp_match[p + 1][q], dp_match[p][q] + 1)
                if q < max_len: 
                    dp_match[p][q + 1] = min(dp_match[p][q + 1], dp_match[p][q] + 1)
      
        for q in range(max_len + 1):
            c = dp_match[3][q]
            match_info[i].append((c, q))  
 
    
    for i in range(n + 1):
        for e in range(m + 1):
            if dp[i][e] == -1:
                continue
            if i < n:  
                dp[i + 1][e] = max(dp[i + 1][e], dp[i][e])  
                if e + 1 <= m:  
                    dp[i + 1][e + 1] = max(dp[i + 1][e + 1], dp[i][e])            
            if i < n and match_info[i]: 
                for c, l in match_info[i]:  
                    if e + c <= m and i + l <= n:
                        dp[i + l][e + c] = max(dp[i + l][e + c], dp[i][e] + 1)
 
  
    max_substrings = 0
    for e in range(m + 1):
        max_substrings = max(max_substrings, dp[n][e])
    return max_substrings

试题5:超市里的货物架调整

问题描述: 在这里插入图片描述

def solution(n: int, m: int, s: str, c: str) -> int:
    # 统计货架上每个商品的出现次数
    from collections import Counter
    count = Counter(s)
    
   
    customers_list = list(c)
    
    # 初始化一个变量来记录可以卖出的商品数量
    sold_count = 0
    
    for item in customers_list:
        if count[item] > 0:
            sold_count += 1
            count[item] -= 1
    
    return sold_count

if __name__ == '__main__':
    print(solution(3, 4, "abc", "abcd") == 3)
    print(solution(4, 2, "abbc", "bb") == 2)
    print(solution(5, 4, "bcdea", "abcd") == 4)

试题6:观光景点组合得分问题

问题描述: 小R正在研究一组观光景点,每个景点都有一个评分,保存在数组 values 中,其中 values[i] 表示第 i 个观光景点的评分。同时,景点之间的距离由它们的下标差 j - i 表示。

一对景点 (i < j) 的观光组合得分为 values[i] + values[j] + i - j,也就是两者评分之和减去它们之间的距离。

小R想知道,在哪种情况下能够获得观光景点组合的最高得分。

def solution(values: list) -> int:
    n = len(values)
    if n < 2:
        return 0  # 如果数组长度小于2,无法形成组合,返回0或其他适当值
    
    # 初始化
    max_i_plus_values = values[0] + 0  # 初始时i=0
    max_score = values[0] + values[1] + 0 - 1  # 初始组合 (0,1)
    
    # 从第二个元素开始遍历
    for j in range(1, n):
        # 计算当前j的values[j] - j
        current = values[j] - j
        
        # 更新最大组合得分
        max_score = max(max_score, max_i_plus_values + current)
        
        # 更新max_i_plus_values
        max_i_plus_values = max(max_i_plus_values, values[j] + j)
    
    return max_score
 
if __name__ == '__main__':
    # 测试样例1
    print(solution(values=[8, 3, 5, 5, 6]) == 11)  # 输出: True
    
    # 测试样例2
    print(solution(values=[10, 4, 8, 7]) == 16)    # 输出: True
    
    # 测试样例3
    print(solution(values=[1, 2, 3, 4, 5]) == 8)  # 输出: True

试题7:数组元素之和最小化

问题描述: 小C希望构造一个包含n个元素的数组,且满足以下条件:

数组中的所有元素两两不同。 数组所有元素的最大公约数为 k。 数组元素之和尽可能小。 任务是输出该数组元素之和的最小值。

def solution(n: int, k: int) -> int:
    multiples = []
    current_multiple = k
    while len(multiples) < n:
        multiples.append(current_multiple)
        current_multiple += k
    result = sum(multiples)
    
    return result

if __name__ == '__main__':
    print(solution(n = 3, k = 1) == 6)
    print(solution(n = 2, k = 2) == 6)
    print(solution(n = 4, k = 3) == 30)

试题8:最少前缀操作问题

问题描述: 小U和小R有两个字符串,分别是S和T,现在小U需要通过对S进行若干次操作,使其变成T的一 前缀。操作可以是修改S的某一个字符, 或者删除S末尾的字符。现在你需要帮助小U计算出,最少 需要多少次操作才能让S变成T的前缀。

def solution(S: str, T: str) -> int:
    len_S = len(S)
    len_T = len(T)
    
    # 计算需要删除的字符数量
    deletions = max(0, len_S - len_T)
    
    # 截断 S,使其长度不超过 T
    S_new = S[:len_T] if len_S > len_T else S
    
    # 计算需要修改的字符数量
    modifications = 0
    for i in range(len(S_new)):
        if S_new[i] != T[i]:
            modifications += 1
    
    # 总操作次数
    total_operations = deletions + modifications
    return total_operations
 
if __name__ == '__main__':
    print(solution("aba", "abb") == 1)          # 输出: True
    print(solution("abcd", "efg") == 4)         # 输出: True
    print(solution("xyz", "xy") == 1)           # 输出: True
    print(solution("hello", "helloworld") == 0) # 输出: True
    print(solution("same", "same") == 0)        # 输出: True

试题9:最大矩形面积问题

问题描述: 在这里插入图片描述

def solution(n, array):
    max_area = 0  # 用于记录最大面积
    
    # 遍历所有可能的 k 值
    for k in range(1, n + 1):
        # 遍历数组,计算以每个元素为起点的 k 个相邻元素的最小值
        for i in range(n - k + 1):
            # 计算当前 k 个相邻元素的最小值
            min_height = min(array[i:i + k])
            # 计算面积
            area = k * min_height
            # 更新最大面积
            if area > max_area:
                max_area = area
    
    return max_area

if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, [1, 2, 3, 4, 5]) == 9)
    print(solution(6, [5, 4, 3, 2, 1, 6]) == 9)
    print(solution(4, [4, 4, 4, 4]) == 16)

试题10:环形数组中的最大贡献值

问题描述: 在这里插入图片描述

def solution(n: int, a: list) -> int:
    max_contribution = 0
    
    # 遍历所有可能的下标对 (i, j)
    for i in range(n):
        for j in range(n):
            if i != j:
                # 计算最短距离
                dist = min(abs(i - j), n - abs(i - j))
                
                # 计算贡献值
                contribution = (a[i] + a[j]) * dist
                
                # 更新最大贡献值
                if contribution > max_contribution:
                    max_contribution = contribution
    
    return max_contribution

if __name__ == '__main__':
    print(solution(n = 3, a = [1, 2, 3]) == 5)
    print(solution(n = 4, a = [4, 1, 2, 3]) == 12)
    print(solution(n = 5, a = [1, 5, 3, 7, 2]) == 24)