得物笔试 得物秋招 得物笔试题 0920
笔试时间:2025年9月20日
往年笔试合集:
第一题:洗盘子
题目描述:小A在餐馆打工,他的主要工作就是洗盘子。某一天餐厅有 n 个盘子需要清洗,从上到下编号 1-n,小A只会每次拿最上面连续的若干个编号连续的盘子 i-j,然后按照 i-j 的顺序来洗它们。
现在,给出一个人洗这个盘子的顺序,请你判断一下是否可能是小A洗盘子的顺序。
输入描述
第一行一个整数 t 表示数据组数。
对于每组数据:
- 第一行一个整数 n
- 第二行 n 个整数 a₁-aₙ,数字间两两有空格隔开,表示某个人洗盘子的顺序
数据范围:1≤t≤10, 1≤n≤1000
输出描述
输出 t 行,每行一个单词,如果可能是小A洗的,则输出 yes,否则输出 no。
样例输入
2
5
1 2 5 4 3
5
1 2 5 3 4
样例输出
yes
no
样例说明: 第一组样例:先拿出盘子1,再拿出盘子2,再拿出盘子3~5。 第二组样例:不可能是小A洗的。
参考题解
解题思路:
- 将输入序列分割成多个连续递减的子序列(段)。分割规则是当当前元素大于前一个元素时,结束当前段并开始新段。
- 检查每个段内的数字是否构成连续的数值序列。对于长度大于1的段,要求相邻元素必须严格递减且差值为1。
- 确保段与段之间满足递增关系,即后一段的最小值必须大于前一段的最大值。
C++:
#include <iostream> #include <vector> #include <algorithm> using namespace std; bool is_valid_sequence(vector<int>& arr) { int n = arr.size(); if (n == 0) return true; vector<vector<int>> segments; vector<int> current_segment; current_segment.push_back(arr[0]); for (int i = 1; i < n; i++) { if (arr[i] < arr[i-1]) { current_segment.push_back(arr[i]); } else { segments.push_back(current_segment); current_segment.clear(); current_segment.push_back(arr[i]); } } segments.push_back(current_segment); // Check each segment for (auto& segment : segments) { if (segment.size() > 1) { for (int j = 1; j < segment.size(); j++) { if (segment[j-1] - segment[j] != 1) { return false; } } } } // Check segments order for (int i = 1; i < segments.size(); i++) { int prev_max = *max_element(segments[i-1].begin(), segments[i-1].end()); int curr_min = *min_element(segments[i].begin(), segments[i].end()); if (curr_min <= prev_max) { return false; } } return true; } int main() { int t; cin >> t; while (t--) { int n; cin >> n; vector<int> arr(n); for (int i = 0; i < n; i++) { cin >> arr[i]; } if (is_valid_sequence(arr)) { cout << "yes" << endl; } else { cout << "no" << endl; } } return 0; }
Java:
import java.util.*; public class Main { public static boolean isValidSequence(int[] arr) { int n = arr.length; if (n == 0) return true; List<List<Integer>> segments = new ArrayList<>(); List<Integer> currentSegment = new ArrayList<>(); currentSegment.add(arr[0]); for (int i = 1; i < n; i++) { if (arr[i] < arr[i-1]) { currentSegment.add(arr[i]); } else { segments.add(new ArrayList<>(currentSegment)); currentSegment.clear(); currentSegment.add(arr[i]); } } segments.add(currentSegment); // Check each segment for (List<Integer> segment : segments) { if (segment.size() > 1) { for (int j = 1; j < segment.size(); j++) { if (segment.get(j-1) - segment.get(j) != 1) { return false; } } } } // Check segments order for (int i = 1; i < segments.size(); i++) { int prevMax = Collections.max(segments.get(i-1)); int currMin = Collections.min(segments.get(i)); if (currMin <= prevMax) { return false; } } return true; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int t = sc.nextInt(); while (t-- > 0) { int n = sc.nextInt(); int[] arr = new int[n]; for (int i = 0; i < n; i++) { arr[i] = sc.nextInt(); } if (isValidSequence(arr)) { System.out.println("yes"); } else { System.out.println("no"); } } sc.close(); } }
Python:
def is_valid_sequence(arr): n = len(arr) if n == 0: return True segments = [] current_segment = [arr[0]] for i in range(1, n): if arr[i] < arr[i - 1]: current_segment.append(arr[i]) else: segments.append(current_segment) current_segment = [arr[i]] segments.append(current_segment) for segment in segments: if len(segment) > 1: for j in range(1, len(segment)): if segment[j - 1] - segment[j] != 1: return False for i in range(1, len(segments)): prev_max = max(segments[i - 1]) curr_min = min(segments[i]) if curr_min <= prev_max: return False return True t = int(input().strip()) for _ in range(t): n = int(input().strip()) arr = list(map(int, input().split())) if is_valid_sequence(arr): print("yes") else: print("no")
第二题:从子序列到子串
题目描述:小钟有一个长度为 n 的字符串 s。小钟可以对 s 执行如下操作:删除 s 的一个字符,并拼接剩下的字符串。例如,字符串 "abcd",小钟可以删除第三个字符,从而得到新的字符串 "abd"。
某一天,小钟得到了另一个长度为 m 的字符串 t。现在,小钟想知道最少删除 s 多少个字符,才能使得 t 作为 s 的某个连续子串出
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025 春招笔试合集 文章被收录于专栏
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南