京东1007秋招笔试真题解析
- 2026-11-05 09:51:53
关注我们,每周更新两到三次大厂最新笔试题解析
前言
难度适中。前两题都是类似比较麻烦的模拟,比较考验代码能力和细节。最后一题其实只是一个简单的动态规划,但是加上路径打印以后,很多同学就不会做了,还是需要把动态规划的路径打印的套路学一学的。
小红的夹吃棋
在一个3*3的棋盘上,小红和小紫正在玩“夹吃棋”。
所谓“夹吃棋”,即如果存在一个白子,它的两侧(横向或者纵向) 相邻都是黑子,则这个棋子将被“夹吃”,对于黑棋亦然。
如果一个棋盘的局面没有一方被夹吃,或者黑白双方都被对面夹吃,则认为是平局。如果只有一方夹吃了另一方,则认为夹吃方赢,被夹吃方输。
小红执黑棋,小紫执白棋,现在给定一个局面,请你判断当前棋局是谁获胜。
输入描述
第一行输入一个正整数t,代表询问的次数。
接下来每组询问输入三行,每行是一个长度为3的字符串,字符串仅由“o””*““.”组成。其中o代表白棋, * 代表黑棋,.代表未放置棋子
输出描述
对于每个棋局,输出一行字符串表示答案,小红获胜输出”kou”,小紫获胜输出"yukari”,平局输出”draw”。
示例1
输入
3
...
o*o
...
o**
ooo
..*
o*o
*o*
o*o
输出
yukari
kou
draw
思路与代码
第一题测试用例非常宽松,直接暴力解就可以AC了。通过遍历可能形成连线的所有位置组合,检查是否有玩家获胜或平局。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class JD {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = Integer.parseInt(scanner.nextLine());
List<String> res = new ArrayList<>();
List<int[]> list = new ArrayList<>();
list.add(new int[]{0,1});
list.add(new int[]{1,0});
list.add(new int[]{1,1});
list.add(new int[]{1,2});
list.add(new int[]{2,1});
for (int j = 0; j < t; j++) {
char[][] chars = new char[3][3];
for (int i = 0; i < 3; i++) {
String s = scanner.nextLine();
chars[i] = s.toCharArray();
}
boolean a = false, b = false; //a小红 小红黑旗, *为黑旗
for (int i = 0; i < list.size(); i++) {
int[] point = list.get(i);
int x = point[0], y = point[1];
if (chars[x][y] == 'o'){
if (x == 0){
if (chars[x][y-1] == '*' && chars[x][y+1] == '*') a = true;
}
if (x == 1){
if (y == 0){
if (chars[x+1][y] == '*' && chars[x-1][y] == '*') a = true;
}
if (y == 1){
if (chars[x][y-1] == '*' && chars[x][y+1] == '*') a = true;
if (chars[x-1][y] == '*' && chars[x+1][y] == '*') a = true;
}
if (y == 2){
if (chars[x+1][y] == '*' && chars[x-1][y] == '*') a = true;
}
}
if (x == 2){
if (chars[x][y-1] == '*' && chars[x][y+1] == '*') a = true;
}
}
else if (chars[x][y] == '*'){
if (x == 0){
if (chars[x][y-1] == 'o' && chars[x][y+1] == 'o') b = true;
}
if (x == 1){
if (y == 0){
if (chars[x+1][y] == 'o' && chars[x-1][y] == 'o') b = true;
}
if (y == 1){
if (chars[x][y-1] == 'o' && chars[x][y+1] == 'o') b = true;
if (chars[x-1][y] == 'o' && chars[x+1][y] == 'o') b = true;
}
if (y == 2){
if (chars[x+1][y] == 'o' && chars[x-1][y] == 'o') b = true;
}
}
if (x == 2){
if (chars[x][y-1] == 'o' && chars[x][y+1] == 'o') b = true;
}
}
}
if (a && b){
res.add("draw");
}else if (a){
res.add("kou");
}else if (b){
res.add("yukari");
}else{
res.add("draw");
}
}
for (String re : res) {
System.out.println(re);
}
}
}
小红玩游戏
小红正在玩一个《兽》的游戏。
在这个游戏中,有n个单位,每个单位的身份是“人”或者“兽”。每个人只知道自己的身份,不知道别人的身份。每个人的战斗力为ai。
当两个单位相遇的时候,首先第一环节是确认身份 (每个人可能会告诉对方自己身份,也可能隐藏)。
如果一个兽得知了对方是人,那么兽会直接攻击人,两方发生战斗;
如果一个人得知了对方是兽,那么他会权衡双方的战斗力: 只有自己的战斗力大于对方时他才会发起攻击。
如果两个单位的阵营相同,则无事发生。
当两个单位攻击时,如果他们的战斗力相等,则最终同归于尽。如果某一方战斗力高,则战斗力高的将把对方杀死。
现在小红进行了m轮遭遇 (每次选两个单位遭遇),请你输出最终的存活情况。
请注意,如果选择遭遇的两方存在某一方已经死亡,显然也不会发生战斗。
输入描述
第一行输入两个正整数n,m,代表单位数量、回合数。
接下来的n行,每行输入一个字符串Si、一个正整数ai,分别代表第i个单位的 身份、战斗力。
接下来的m行,每行输入两个正整数u,v以及两个字符C1,C2,代表第u个单位和第v个单位遭遇。C1是Y字符代表u向u公布自己的身份,N代表隐藏身份;C2是Y字符代表u向u公布自己的身份,N代表隐藏身份。
1<=n<=10^5
1<=ai<=10^9
1<=u,v<=n
si为”human”和”monster”中的一个,"human"代表人,"monster"代表兽。
输出描述
输出一个长度为n,的字符串,仅由Y和N组成。Y代表第i个单位存活,N代表死亡。
示例1
输入
4 3
human 2
monster 3
monster 10
monster 1
1 2 N Y
1 4 Y N
2 3 Y Y
输出
YYYN
说明
第一轮,第一个单位 (人) 和第二个 (兽)遭遇,兽公布了自己的身份,由于人的战斗力低于兽,他不会选择战斗。
第二轮,第一个单位 (人) 和第四个 (兽)遭遇,人公布了自己的身份,兽直接选择战斗,但人获胜。
第三轮,两个单位都公布了身份,由于身份相同,因此不会战斗。最终只有第四个单位死亡。
思路与代码
这一题就是使用一个循环遍历每一场战斗,检查参与战斗的两个角色是否满足战斗条件。
如果满足战斗条件,根据战斗结果更新角色的能力值。最后,根据每个角色的能力值,输出战斗后的状态。
#include<bits/stdc++.h>
using namespace std;
void solve() {
int n,m;
cin >> n >> m;
vector<int> power(n);
vector<int> isHuman(n,0);
for(int i = 0;i < n;i++) {
string type;
int p;
cin >> type >> p;
if(type == "human") {
isHuman[i] = 1;
}
power[i] = p;
}
for(int i = 0;i < m;i++) {
int u,v;
char c1,c2;
cin >> u >> v >> c1 >> c2;
u--,v--;
if(!(isHuman[u] ^ isHuman[v])) continue;
if(power[u] == 0 || power[v] == 0) continue;
bool fight = false;
if(c2 == 'Y') {
if(!isHuman[u] || power[u] > power[v]) {
int mn = min(power[u],power[v]);
if(power[v] == mn) {
power[v] = 0;
}
if(power[u] == mn) {
power[u] = 0;
}
fight = true;
}
}
if(fight) continue;
if(c1 == 'Y') {
if(!isHuman[v] || power[v] > power[u]) {
int mn = min(power[u],power[v]);
if(power[v] == mn) {
power[v] = 0;
}
if(power[u] == mn) {
power[u] = 0;
}
}
}
}
for(int p : power) {
if(p == 0) {
cout << "N";
}else {
cout << "Y";
}
}
cout << "\n";
}
int main() {
solve();
}
小红的笔试
小红正在参加笔试,已知笔试一共有n个编程题,每个编程题有若干个测试用例,小红获得的分数和通过的测试用例数量成正比。
对于一个题而言,小红可以写一个暴力算法获得部分分,这样相对的比较节省时间,另外她还可以直接尝试正解,这样可以获得满分,但需要花费更多的时间。
现在给定了总时间,以及每个题目暴力算法的用时和得分、正确算法的用时和得分。
请你帮小红规划一个做题方案,可以在有限的时间内获得更多分数。
输入描述
第一行输入两个正整数n,t,代表题目数量,以及笔试的总时长。
接下来n行,每行输入四个正整数ti1,si1,ti2,82,分别代表小红写出正解的 用时,正确算法的得分,小红写暴力算法的用时,暴力算法的得分。
1 <= n,t <= 2000
1 <= tiz <=ti1 < 2000
1 <=si2 <=si1 <=10^5
输出描述
输出一个长度为n的字符串,第i个字符代表第i道题的策略:
如果这道题写暴力算法,则用字符B表示;如果写正确算法,则用字符A表示;如果放弃此题(不耗时间,但这道题0分) ,则用F表示。
请务必保证总耗时不超过t,且总得分尽可能大。如果有多种做题方案都能拿到最高分数,输出任意一种即可。
示例1
输入
3 10
4 10 2 5
4 20 2 5
6 20 1 15
输出
AAB
说明
前两题写正解,第三题写暴力算法,这样总耗时为9,总得分为10+20+15=45。可以证明,这样安排是最优的。
思路与代码
这个题主要是通过动态规划找到了在总时间限制下最大总价值的任务选择组合,并输出了这个组合。它使用了常见的动态规划思想,将问题分解为子问题,并记录了选择路径以恢复最佳解。
#include<bits/stdc++.h>
using namespace std;
void solve() {
int n,t;
cin >> n >> t;
vector<vector<int>> info(n,vector<int>(4));
for(int i = 0;i < n;i++) {
int t1,s1,t2,s2;
cin >> t1 >> s1 >> t2 >> s2;
info[i] = {t1,s1,t2,s2};
}
vector<vector<int>> dp(n + 1,vector<int>(t + 1,0));
vector<vector<pair<int,int>>> f(n + 1,vector<pair<int,int>>(t + 1,{-1,-1}));
for(int i = 1;i <= n;i++) {
int t1 = info[i-1][0],s1 = info[i-1][1],t2 = info[i-1][2],s2 = info[i-1][3];
for(int j = 0;j <= t;j++) {
dp[i][j] = dp[i-1][j];
f[i][j] = {i-1,j};
if(j >= t1 && s1 + dp[i-1][j-t1] > dp[i][j]) {
dp[i][j] = s1 + dp[i-1][j-t1];
f[i][j] = {i-1,j-t1};
}
if(j >= t2 && s2 + dp[i-1][j-t2] > dp[i][j]) {
dp[i][j] = s2 + dp[i-1][j-t2];
f[i][j] = {i-1,j-t2};
}
}
}
int mx = 0;
int x = -1,y = -1;
for(int i = 0;i <= n;i++) {
for(int j = 0;j <= t;j++) {
if(dp[i][j] > mx) {
mx = dp[i][j];
x = i,y = j;
}
}
}
string ans(n,'F');
while(x != -1 && y != -1 && f[x][y].first != -1 && f[x][y].second != -1) {
int fx = f[x][y].first;
int fy = f[x][y].second;
if(dp[x][y] != dp[fx][fy]) {
int i = x;
int t1 = info[i-1][0],s1 = info[i-1][1],t2 = info[i-1][2],s2 = info[i-1][3];
if(y == fy + t1 && dp[x][y] == s1 + dp[fx][fy]) {
ans[i-1] = 'A';
}
if(y == fy + t2 && dp[x][y] == s2 + dp[fx][fy]) {
ans[i-1] = 'B';
}
}
x = fx;
y = fy;
}
cout << ans << endl;
}
int main() {
solve();
}
最后插一下我们的进阶一对一辅导啦
我们是一个针对技术岗(前后端开发、测试、测开、大数据开发)校招一对一进阶提高的工作室。我们从2020年2月份开始,迄今整整三年的时间,带领300+学员斩获1500+大厂offer,参加活动的同学人均5个中大厂offer以上,以下是我们活动内容的介绍! 万诺coding
我们主要是针对有一定基础的同学提供一对一笔试和面试辅导,针对每个同学不同的情况定制内容,包括但不限于“数据结构与算法”/“计算机基础知识”/“项目梳理”/“面试技巧”/“面试复盘”等内容。
摸底测试:如果有兴趣深入了解我们的活动,需要先参加我们的“摸底测试”(类似面试),方便我们了解你的具体情况(主要是code能力和计算机素养),定制出相应的辅导计划。同时这也是一个双向筛选的过程,如果基础过差的同学,抱歉我们可能无法辅导(基础过差的同学一对一辅导成本过高,对双方都不适合);摸底测试通过的同学,我们会定制化一个针对性的提高计划。然后你再考虑是否参加我们的活动。
承诺保offer:通过摸底测试后,我们会针对每个同学的情况给定一个“保offer”计划。然后同学可以根据自己的实际情况考虑参不参加我们的活动。
有兴趣的同学可以扫码添加我们的微信(whynotlab)