百度笔试 百度秋招 百度笔试题 0923
笔试时间:2025年9月23日
往年笔试合集:
第一题
Tk有一个仅由字符'0'和'1'构成的字符串s,长度为n。Tk希望通过以下两种操作,每次操作二选一,使得字符串中所有的0都不在1之后:
- 操作1:选择两个相邻的字符s[i]和s[i+1],当且仅当s[i]='0'且s[i+1]='0'时,将它们同时修改为'1'
- 操作2:选择两个相邻的字符s[i]和s[i+1],当且仅当s[i]='1'且s[i+1]='0'时,将它们修改为'0'和'1'
请计算使字符串满足"所有的0都不在1之后"这一条件的最少操作次数。
输入描述
输出描述
输出一个整数,表示使字符串满足条件的最少操作次数。
样例输入
5
10001
样例输出
2
第一个操作使用操作1,将字符串"10001"中第3、4位的"00"变为"11",得到"10111"; 第二个操作使用操作2,将字符串"10111"中第1、2位的"10"变为"01",得到"01111",此时所有的1均位于0之后。
参考题解
解题思路:
目标是让所有0在前,所有1在后。核心观察:
- 操作1:消除一对相邻的0(减少0的总数)
- 操作2:将0向左移动(调整0的相对位置)
使用动态规划:
- dp[i]表示处理前i个0的最小代价
- 可以单独处理第i个0,或将第i-1和第i个0配对处理
- 状态转移:dp[i] = min(dp[i-1] + 前缀1数量, dp[i-2] + 两0间1数量 + 1)
C++:
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n;
cin >> n;
string s;
cin >> s;
vector<int> zero_indices;
vector<int> prefix_ones(n + 1, 0);
for (int i = 0; i < n; i++) {
prefix_ones[i + 1] = prefix_ones[i];
if (s[i] == '0') {
zero_indices.push_back(i);
} else {
prefix_ones[i + 1]++;
}
}
int num_zeros = zero_indices.size();
if (num_zeros < 2) {
cout << 0 << endl;
return;
}
vector<int> dp(num_zeros + 1, 0);
int first_zero_index = zero_indices[0];
dp[1] = prefix_ones[first_zero_index];
for (int i = 2; i <= num_zeros; i++) {
int current_zero_index = zero_indices[i - 1];
int prev_zero_index = zero_indices[i - 2];
int cost_singleton = dp[i - 1] + prefix_ones[current_zero_index];
int ones_between = prefix_ones[current_zero_index] - prefix_ones[prev_zero_index];
int cost_pair = dp[i - 2] + ones_between + 1;
dp[i] = min(cost_singleton, cost_pair);
}
cout << dp[num_zeros] << endl;
}
int main() {
solve();
return 0;
}
Java:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
solve(sc);
}
public static void solve(Scanner sc) {
int n = sc.nextInt();
String s = sc.next();
List<Integer> zeroIndices = new ArrayList<>();
int[] prefixOnes = new int[n + 1];
for (int i = 0; i < n; i++) {
prefixOnes[i + 1] = prefixOnes[i];
if (s.charAt(i) == '0') {
zeroIndices.add(i);
} else {
prefixOnes[i + 1]++;
}
}
int numZeros = zeroIndices.size();
if (numZeros < 2) {
System.out.println(0);
return;
}
int[] dp = new int[numZeros + 1];
int firstZeroIndex = zeroIndices.get(0);
dp[1] = prefixOnes[firstZeroIndex];
for (int i = 2; i <= numZeros; i++) {
int currentZeroIndex = zeroIndices.get(i - 1);
int prevZeroIndex = zeroIndices.get(i - 2);
int costSingleton = dp[i - 1] + prefixOnes[currentZeroIndex];
int onesBetween = prefixOnes[currentZeroIndex] - prefixOnes[prevZeroIndex];
int costPair = dp[i - 2] + onesBetween + 1;
dp[i] = Math.min(costSingleton, costPair);
}
System.out.println(dp[numZeros]);
}
}
Python:
import sys
def solve():
n = int(sys.stdin.readline())
s = sys.stdin.readline().strip()
zero_indices = []
prefix_ones = [0] * (n + 1)
for i in range(n):
prefix_ones[i + 1] = prefix_ones[i]
if s[i] == '0':
zero_indices.append(i)
else:
prefix_ones[i + 1] += 1
num_zeros = len(zero_indices)
if num_zeros < 2:
print(0)
return
dp = [0] * (num_zeros + 1)
first_zero_index = zero_indices[0]
dp[1] = prefix_ones[first_zero_index]
for i in range(2, num_zeros + 1):
current_zero_index = zero_indices[i - 1]
prev_zero_index = zero_indices[i - 2]
cost_singleton = dp[i - 1] + prefix_ones[current_zero_index]
ones_between = prefix_ones[current_zero_index] - prefix_ones[prev_zero_index]
cost_pair = dp[i - 2] + ones_between + 1
dp[i] = min(cost_singleton, cost_pair)
print(dp[num_zeros])
solve()
第二题
我们所熟知的按位异或可以等价为二进制下的不进位加法;在本题中,我们将其称为2进制异或。
当在任意进制b下(2≤b≤10),我们定义一种无进位加法,也称b进制异或。其操作过程为:先将两个十进制数转换为b进制表示,然后将它们的对应数位相加并对b取模,作为结果的对应位,不产生向高位的进位。所有位数计算完成后,将得到的b进制结果转换回十进制。
给定长度为n的十进制数组a。
对任意子区间[l,r],先计算该区间在每个进制(b=2,3,...,10)下的异或和,再取这9个值的最大值与最小值之差,作为该子区间的权值。
现在需要处理m次查询,每次给定子区间[l,r],请计算并输出该子区间的权值。
输入描述
输出描述
对于每次查询,新起一行,输出一个整数,表示该子区间的权值。
样例输入
14 2
2 5 15 19 4 7 9 12 15 20 20 18 19 12
6 6
3 12
样例输出
0
92
参考题解
解题思路:
使用前缀和技巧处理区间查询。对每个进制b(2到10):
- 预计算前缀异或和数组
- 区间[l,r]的异或和 = prefix[r] - prefix[l-1](在b进制下的无进位减法)
- 收集9个进制下的结果,求最大值与最小值的差
C++:
#include <bits/stdc++.h>
using namespace std;
long long b_ary_xor(long long n1, long long n2, int b) {
long long result = 0;
long long power_of_b = 1;
while (n1 > 0 || n2 > 0) {
int digit1 = n1 % b;
int digit2 = n2 % b;
int sum_digit = (digit1 + digit2) % b;
result += sum_digit * power_of_b;
n1 /= b;
n2 /= b;
power_of_b *= b;
}
return result;
}
long long b_ary_subtract(long long n1, long long n2, int b) {
long long result = 0;
long long power_of_b = 1;
while (n1 > 0 || n2 > 0) {
int digit1 = n1 % b;
int digit2 = n2 % b;
int diff_digit = (digit1 - digit2 + b) % b;
result += diff_digit * power_of_b;
n1 /= b;
n2 /= b;
power_of_b *= b;
}
return result;
}
int main() {
int n, m;
cin >> n >> m;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<vector<long long>> prefix_xors(11, vector<long long>(n + 1, 0));
for (int b = 2; b
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南
