oppo笔试 oppo笔试题 0802
笔试时间:2025年8月2日
往年笔试合集:
2024春招秋招笔试合集
第一题:回答问题
小 O 回答了若干个问题。你需要判断他是否回答的全是“是”的。具体地,你将得到一个长度为 n 的字符串 s(仅由大小写字母构成),请判断 s 是否由字符串 "yes" 或 "sey"(均不区分大小写)拼接而成。如果是,则输出 "Yes";否则,输出 "No"。
输入描述
每个测试文件均包含多组测试数据。
第一行输入一个整数 T (1 ≤ T ≤ 10⁴),代表数据组数,每组测试数据描述如下:
第一行输入一个整数 n (1 ≤ n ≤ 2 × 10⁵),表示字符串长度;
第二行输入一个长度为 n、仅由大小写字母构成的字符串 s。
除此之外,保证所有测试数据中 n 的总和不超过 2 × 10⁵。
输出描述
对于每组测试数据,新起一行。输出一个字符串,即如果满足条件输出 "Yes";否则输出 "No"。
样例输入
2
6
YeSsEY
3
Yec
样例输出
Yes
No
参考题解
模拟题
C++:
#include <iostream> #include <string> #include <algorithm> using namespace std; int main() { int t; cin >> t; while(t--) { string dummy; cin >> dummy; // 读取空行或其他输入 string s; cin >> s; // 转换为小写 transform(s.begin(), s.end(), s.begin(), ::tolower); if(s.length() % 3 != 0) { cout << "No" << endl; continue; } bool flag = true; for(int i = 0; i < s.length(); i += 3) { string sub = s.substr(i, 3); if(sub != "yes" && sub != "sey") { flag = false; break; } } if(flag) { cout << "Yes" << endl; } else { cout << "No" << endl; } } return 0; }
Java:
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int t = scanner.nextInt(); scanner.nextLine(); // 消耗换行符 for(int testCase = 0; testCase < t; testCase++) { scanner.nextLine(); // 读取空行或其他输入 String s = scanner.nextLine().toLowerCase(); if(s.length() % 3 != 0) { System.out.println("No"); continue; } boolean flag = true; for(int i = 0; i < s.length(); i += 3) { String sub = s.substring(i, Math.min(i + 3, s.length())); if(!sub.equals("yes") && !sub.equals("sey")) { flag = false; break; } } if(flag) { System.out.println("Yes"); } else { System.out.println("No"); } } scanner.close(); } }
Python:
import sys t = int(input()) for _ in range(t): input() s = input().lower() if len(s)%3 != 0: print("No") continue flag = True for i in range(0,len(s), 3): if(s[i:i+3] != "yes" and s[i:i+3] != "sey"): flag = False break if flag: print("Yes") else: print("No")
第二题:包包的简单子数组计数
给定一个长度为(n)的数组 {a₁,a₂,…,aₙ}。对于满足 1≤l≤r≤n 的任意下标对 (l,r),定义
f (l, r) = floor ( (sum 从 i=l 到 r 的 a_i) / (r - l + 1) )
即子数组 aₗ,aₗ₊₁,…,aᵣ 的平均值向下取整。令
v = max (1 ≤ l ≤ r ≤ n 时的 f (l, r))
求满足 1 ≤i≤j≤ n 且 f (i,j)=v 的下标对 (i,j) 的数量。
【子数组】子数组为从原数组中,连续的选择一段元素 (可以全选) 得到的新数组
输入描述
第一行输入一个整数n,( 1 <= n <= 2 * 10^5 )),表示数组长度;
第二行输入n个整数(0<=a_i <= 10^6),表示数组元素。
输出描述
输出一个整数,表示满足条件的(i,j)对的数量。
样例输入
3
3 2 3
样例输出
2
参考题解
本题是数学思维题,首先根据v的定义可知,v的值一定是分母为1,且分子为数组中最大值时,对应的f函数值,因此这是个定值,即v=max(a),接下来只需要统计有多少个连续最大值区间,其中每个长度为len的最大值区间对答案的贡献为len*(len-1)/2,因此遍历数组,对每个连续最大值区间累加后即可得到答案。
C++:
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; ++i) { cin >> a[i]; } int mx = *max_element(a.begin(), a.end()); int i = 0, j = 0; long long ans = 0; while (i < n) { j = i + 1; if (a[i] == mx) { while (j < n && a[j] == mx) { j++; } // 计算连续k个元素的子数组数量:k*(k+1)/2 long long k = j - i; ans += k * (k + 1) / 2; } i = j; } cout << ans << endl; return 0; }
Java:
import java.util.Scanner; import java.util.Arrays; public class MaxSubarrays { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int[] a = new int[n]; for (int i = 0; i < n; i++) { a[i] = scanner.nextInt(); } // 找到数组中的最大值 int mx = Arrays.stream(a).max().getAsInt(); int i = 0, j = 0; long ans = 0; while (i < n) { j = i + 1; if (a[i] == mx) { while (j < n && a[j] == mx) { j++; } // 计算连续k个元素的子数组数量:k*(k+1)/2 long k = j - i; ans += k * (k + 1) / 2; } i = j; } System.out.println(ans); scanner.close(); } }
Python:
import sys n = int(input()) a = [int(x) for x in input().split()] mx = max(a) i,j = 0,0 ans = 0 while i<n : j = i+1 if a[i] == mx: while(j<n and a[j] == mx): j+=1 ans += (1+(j-i))*(j-i)//2 i=j print(ans)
第三题:小C的棋盘
小C最近迷上了一款战棋游戏。战棋的地图是一张有n个点、m条边的有向图,每个点上放置一个棋子。棋子共有c种颜色,第i种颜色的棋子具有攻击距离ki。棋子只能攻击与自己颜色相同的目标。如果一个棋子不能被任何其他同色棋子在其攻击距离内攻击到,那么小C认为它是安全棋子。现在给出战棋地图信息,请计算安全棋子的总数。【名词解释】有向图:有向图是由一组顶点和一组有向边组成的图,每条边都有起点和终点。
输入描述
第一行输入三个整数 n,m,c(1 ≤ n ≤ 10⁵,0 ≤ m ≤ 10⁵,1 ≤ c ≤ 30),分别表示战棋的点数、边数和颜色数。
第二行输入 n 个整数 c₁,c₂,…,cₙ(1 ≤ cᵢ ≤ c),其中 cᵢ 表示第 i 个棋子的颜色。
第三行输入 c 个整数 k₁,k₂,…,k_c(1 ≤ kᵢ ≤ 10⁹),其中 kᵢ 为颜色 i 棋子的攻击距离。
接下来 m 行,每行输入三个整数 uⱼ,vⱼ,dⱼ(1 ≤ uⱼ,vⱼ ≤ n,1 ≤ dⱼ ≤ 10⁴),表示存在一条从 uⱼ 到 vⱼ 的有向边,边长为 dⱼ。
输出描述
输出一个整数,表示安全棋子的数量。
样例输入
3 3 2
1 2 1
2 1
1 2 3
2 3 1
3 1 2
样例输出
2
说明:
在这个样例中,n = 3,c = 2。棋子分布与参数如下:
节点 1、3 颜色为 1,攻击距离 k₁ = 2;
节点 2 颜色为 2,攻击距离 k₂ = 1;
边集为 1 → 2 (3)、2 → 3 (1)、3 → 1 (2)。
节点 3 到节点 1 的最短路径距离为 2 ≤ k₁,因此节点 1 不安全;其余棋子均安全,总数为 2。
参考题解
本题是多源最短路问题,按照题意的输入建图,然后对每个颜色归类分开处理,对每个颜色,先把所有的点都加到初始优先队列中,然后进行Dijkstra算法,标记所有距离不超过ki的点,没被标记的也就是该颜色的安全棋子了。本题需要注意,每个点无法攻击自己,所以要在跑最短路的同时记录源头是哪个点。时间复杂度<O(c*nlogn)。
C++:
#include <iostream> #include <vector> #include <queue> #include <tuple> #include <limits> using namespace std; typedef long long ll; const ll INF = 1e18; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, c; cin >> n >> m >> c; vector<int> colors(n); for (int i = 0; i < n; ++i) { cin >> colors[i]; --colors[i]; // 0-index } vector<ll> k_list(c); for (int i = 0; i < c; ++i) { cin >> k_list[i]; } vector<vector<pair<int, int>>> graph(n); // {to, weight} for (int i = 0; i < m; ++i) { int u, v, d; cin >> u >> v >> d; graph[u - 1].emplace_back(v - 1, d); // 0-indexed } vector<vector<int>> color_groups(c); for (int i = 0; i < n; ++i) { color_groups[colors[i]].push_back(
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南