校招算法笔面试 | 校招笔面试真题-小红的地砖

题目## 题目

题目链接

题目链接

小红的地砖

题目描述

小红有 n n n 块地砖,小红从第一块地砖开始,要走到第 n n n 块地砖。走到第 i i i 块地砖需要消耗 a i a_i ai 的体力值,小红每次可以选择向前走一步或者向前走两步,求小红走到第 n n n 块地砖时消耗的最小体力值。

输入:

  • 第一行输入一个整数 n n n,表示地砖的数量
  • 第二行输入 n n n 个整数 a i a_i ai,表示走到第 i i i 块地砖需要消耗的体力值

输出:

  • 输出一个整数,表示小红走到第 n n n 块地砖时消耗的最小体力值

解题思路

这是一个动态规划问题,可以通过以下步骤解决:

  1. 关键发现:

    • 每次可以走一步或两步
    • 到达每个位置的最小体力值只与前两个位置有关
    • 需要累加经过的地砖的体力值
  2. 解题策略:

    • 使用dp数组记录到达每个位置的最小体力值
    • 对每个位置,考虑从前一个位置走一步或从前两个位置走两步
    • 选择较小的体力值
  3. 具体步骤:

    • 初始化dp数组,dp[i]表示到达第i个位置的最小体力值
    • 状态转移:dp[i] = min(dp[i-1], dp[i-2]) + a[i]
    • 最后返回dp[n-1]

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
    
    vector<int> dp(n, INT_MAX);
    dp[0] = a[0];
    if(n > 1) dp[1] = a[1];
    
    for(int i = 2; i < n; i++) {
        dp[i] = min(dp[i-1], dp[i-2]) + a[i];
    }
    
    cout << dp[n-1] << endl;
    return 0;
}
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];
        for(int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }
        
        int[] dp = new int[n];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = a[0];
        if(n > 1) dp[1] = a[1];
        
        for(int i = 2; i < n; i++) {
            dp[i] = Math.min(dp[i-1], dp[i-2]) + a[i];
        }
        
        System.out.println(dp[n-1]);
    }
}
n = int(input())
a = list(map(int, input().split()))

dp = [float('inf')] * n
dp[0] = a[0]
if n > 1:
    dp[1] = a[1]

for i in range(2, n):
    dp[i] = min(dp[i-1], dp[i-2]) + a[i]

print(dp[n-1])

算法及复杂度

  • 算法:动态规划
  • 时间复杂度: O ( n ) \mathcal{O}(n) O(n) - 需要遍历一次数组
  • 空间复杂度: O ( n ) \mathcal{O}(n) O(n) - 需要dp数组存储状态

注意:

  1. 需要特别处理n=1和n=2的情况
  2. 初始化dp数组时要用最大值
  3. 状态转移时需要考虑前两个位置
  4. 最终结果是dp[n-1]而不是dp[n]

题目链接

题目链接

小红的回文子串

题目描述

小红拿到了一个字符串。她想知道,该字符串有多少个长度为 k 的连续子串是回文的?

输入:

  • 第一行输入两个正整数 n 和 k,分别代表字符串长度和子串长度
  • 第二行输入一个长度为 n 的、仅由小写字母组成的字符串

输出:

  • 输出一个整数,表示长度为 k 的回文子串数量

解题思路

这是一个字符串处理问题,可以通过以下步骤解决:

  1. 关键发现:

    • 需要检查所有长度为 k 的连续子串
    • 子串总数为 n-k+1 个
    • 每个子串需要判断是否为回文串
  2. 解题策略:

    • 使用滑动窗口遍历所有长度为 k 的子串
    • 对每个子串判断是否为回文
    • 统计回文子串的数量
  3. 具体步骤:

    • 遍历字符串的每个位置 i (0 到 n-k)
    • 检查从位置 i 开始的长度为 k 的子串
    • 判断该子串是否为回文
    • 累计回文子串的数量

代码

#include <bits/stdc++.h>
using namespace std;

// 判断字符串是否为回文
bool isPalindrome(const string& s, int start, int len) {
    int left = start;
    int right = start + len - 1;
    while(left < right) {
        if(s[left] != s[right]) return false;
        left++;
        right--;
    }
    return true;
}

int main() {
    int n, k;
    cin >> n >> k;
    string s;
    cin >> s;
    
    int ans = 0;
    // 遍历所有长度为k的子串
    for(int i = 0; i <= n - k; i++) {
        if(isPalindrome(s, i, k)) {
            ans++;
        }
    }
    
    cout << ans << endl;
    return 0;
}
import java.util.*;

public class Main {
    // 判断字符串是否为回文
    static boolean isPalindrome(String s, int start, int len) {
        int left = start;
        int right = start + len - 1;
        while(left < right) {
            if(s.charAt(left) != s.charAt(right)) return false;
            left++;
            right--;
        }
        return true;
    }
    
    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 ans = 0;
        // 遍历所有长度为k的子串
        for(int i = 0; i <= n - k; i++) {
            if(isPalindrome(s, i, k)) {
                ans++;
            }
        }
        
        System.out.println(ans);
    }
}
def is_palindrome(s, start, length):
    left = start
    right = start + length - 1
    while left < right:
        if s[left] != s[right]:
            return False
        left += 1
        right -= 1
    return True

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

ans = 0
# 遍历所有长度为k的子串
for i in range(n - k + 1):
    if is_palindrome(s, i, k):
        ans += 1

print(ans)

算法及复杂度

  • 算法:滑动窗口 + 回文判断
  • 时间复杂度: O ( n ⋅ k ) \mathcal{O}(n \cdot k) O(nk) - 需要检查 n − k + 1 n-k+1 nk+1 个子串,每个子串需要 O ( k ) \mathcal{O}(k) O(k) 时间判断
  • 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1) - 只需要常数空间存储变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值