🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员
✨ 本系列打算持续跟新得物近期的春秋招笔试题汇总~
💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导
👏 感谢大家的订阅➕ 和 喜欢💗
文章目录
01.假日作业计划
题目描述
K小姐即将进入假期,打算利用这段时间完成积压的作业。由于每天的精力状态不同,她每天能完成的作业数量也有所不同。为了在假期内高效完成作业,同时兼顾身体健康,K小姐制定了一份假日作业计划:每次完成一定量的作业后,都需要休息 1 1 1 天或 2 2 2 天(不能不休息,也不能连续休息超过 2 2 2 天),再继续投入学习。K小姐决定从假期的第 1 1 1 天或第 2 2 2 天开始学习。请问按照这样的计划,K小姐在假期内最多能完成多少作业呢?
输入格式
第一行包含一个正整数 n n n,表示假期的总天数。
第二行包含 n n n 个空格分开的非负整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an,其中 a i a_i ai 表示K小姐在第 i i i 天能完成的作业数量。
输出格式
输出一个整数,表示K小姐在假期内最多能完成的作业总数。
样例输入
5
2 1 2 1 2
样例输出
6
数据范围
1
≤
n
≤
1
0
4
1 \leq n \leq 10^4
1≤n≤104
0
≤
a
i
≤
1
0
4
0 \leq a_i \leq 10^4
0≤ai≤104
题解
本题可以使用动态规划解决。定义状态 f [ i ] [ 0 ] f[i][0] f[i][0] 表示在第 i i i 天学习时能完成的最大作业量, f [ i ] [ 1 ] f[i][1] f[i][1] 表示在第 i i i 天休息时能完成的最大作业量。
状态转移方程为:
f
[
i
]
[
0
]
=
max
(
f
[
i
−
1
]
[
0
]
,
f
[
i
−
1
]
[
1
]
)
f[i][0] = \max(f[i-1][0], f[i-1][1])
f[i][0]=max(f[i−1][0],f[i−1][1])
f
[
i
]
[
1
]
=
f
[
i
−
1
]
[
0
]
+
a
i
f[i][1] = f[i-1][0] + a_i
f[i][1]=f[i−1][0]+ai
其中, a i a_i ai 表示第 i i i 天能完成的作业量。
最终答案为 max ( f [ n ] [ 0 ] , f [ n ] [ 1 ] ) \max(f[n][0], f[n][1]) max(f[n][0],f[n][1]),即第 n n n 天学习或休息时能完成的最大作业总量。
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
参考代码
- Python
n = int(input())
a = list(map(int, input().split()))
f = [[0] * 2 for _ in range(n + 1)]
f[0][1] = float('-inf')
for i in range(1, n + 1):
f[i][0] = max(f[i-1][0], f[i-1][1])
f[i][1] = f[i-1][0] + a[i-1]
print(max(f[n][0], f[n][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[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int[][] f = new int[n + 1][2];
f[0][1] = Integer.MIN_VALUE;
for (int i = 1; i <= n; i++) {
f[i][0] = Math.max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + a[i - 1];
}
System.out.println(Math.max(f[n][0], f[n][1]));
}
}
- Cpp
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e4 + 5;
int n, a[N];
int f[N][2];
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
f[0][1] = -2e9;
for (int i = 1; i <= n; i++) {
f[i][0] = max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + a[i - 1];
}
cout << max(f[n][0], f[n][1]) << endl;
return 0;
}
02.K小姐的项链
题目描述
K小姐收到了一条由 0 0 0 和 1 1 1 组成的项链作为生日礼物。由于项链的特殊设计,如果其中连续出现 110 110 110 这样的子串,项链就会自动断开。为了避免这种情况发生,K小姐想知道这条项链中最长的不包含 110 110 110 子串的连续部分的长度是多少。
输入格式
输入一行,包含一个只由 0 0 0 和 1 1 1 组成的字符串 S S S,表示项链的序列,其长度 1 ≤ ∣ S ∣ ≤ 1 0 6 1 \leq |S| \leq 10^6 1≤∣S∣≤106。
输出格式
输出一个整数,表示最长的不包含 110 110 110 子串的连续部分的长度。
样例输入
01101001
样例输出
4
数据范围
- 1 ≤ ∣ S ∣ ≤ 1 0 6 1 \leq |S| \leq 10^6 1≤∣S∣≤106
题解
这道题可以使用滑动窗口的思想来解决。我们维护一个滑动窗口,窗口内的子串就是当前不包含 110 110 110 的连续部分。遍历整个字符串,每次判断以当前位置结尾的最后三个字符是否为 110 110 110,如果不是,就将当前字符纳入窗口,并更新最长长度;如果是,就将窗口左端点移动到当前位置的前两个字符,重新开始统计。
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)。
参考代码
- Python
s = input()
n = len(s)
max_len = 0
cur_len = 0
for i in range(n):
cur_len += 1
if i >= 2 and s[i-2:i+1] == "110":
cur_len = 2
max_len = max(max_len, cur_len)
print(max_len)
- Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
int n = s.length();
int maxLen = 0;
int curLen = 0;
for (int i = 0; i < n; i++) {
curLen++;
if (i >= 2 && s.substring(i-2, i+1).equals("110")) {
curLen = 2;
}
maxLen = Math.max(maxLen, curLen);
}
System.out.println(maxLen);
}
}
- Cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
int n = s.size();
int maxLen = 0;
int curLen = 0;
for (int i = 0; i < n; i++) {
curLen++;
if (i >= 2 && s.substr(i-2, 3) == "110") {
curLen = 2;
}
maxLen = max(maxLen, curLen);
}
cout << maxLen << endl;
return 0;
}
写在最后
📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取~