京东笔试 京东笔试题 0809

笔试时间:2025年8月9日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:子序列的字典序

现在有一个长度为 n 的数字序列,每个数都在 1~k 的范围内,且 1~k 内每个数字都至少出现过一次。现在我们想在这其中找一个子序列,使得 1~k 恰好出现一次,且字典序最小。请你通过程序得出结果。我们认为:B 是 A 的子序列,当且仅当可以从 A 中删除 0 个或任意个元素之后按照原来的顺序拼接起来得到 B。序列 A 的字典序小于 B,当且仅当存在一个位置 k,使得 A[k] < B[k] 且 A[i] = B[i](i = 1..k-1)。

输入描述

第一行两个空格隔开的正整数 n 和 k;

第二行 n 个空格隔开的正整数,表示该数字序列 a。

约束:1 ≤ k ≤ n ≤ 5×10⁴,1 ≤ aᵢ ≤ k

输出描述

输出一行 k 个数字,表示字典序最小的子序列。不要输出行末空格。

样例输入

5 3  

2 1 3 3 2

样例输出

1 3 2  

提示:其中一种可行的方案为:2(1)3(3)2,选定括号中的数字,构成子序列,可知此时字典序最小。

参考题解

本题使用贪心+单调栈的的思路, 问题本质分析:需要从原数组中选出长度为 k 的子序列(保持原顺序),且该子序列的字典序最小。字典序最小的核心是「前面的元素尽可能小」,这天然指向「贪心策略」—— 每一步都选择当前能选的最小元素。贪心的约束:选择小元素时不能 “只顾眼前”,必须保证后面还有足够的元素来凑齐 k 个。例如,若当前栈顶元素较大,但后面再也没有该元素了,就不能弹出它(否则凑不够 k 个)。因此需要统计每个元素剩余的出现次数,作为能否弹出栈顶的依据。单调栈的适配性:要维护 “前面元素尽可能小” 的序列,单调栈是天然的工具。栈可以动态维护已选元素,通过弹出 “较大且后续仍有出现” 的栈顶元素,确保新加入的元素能让序列更优(字典序更小)。同时栈的长度可以直观地控制在 k 以内,满足子序列长度要求。去重需求:若问题隐含 “子序列元素不重复”(从代码中 inStack 的判断可推测),则需要额外记录元素是否已在栈中,避免重复加入破坏唯一性。因此,贪心策略保证了 “选最小” 的核心目标,单调栈提供了动态维护序列的高效方式,剩余次数统计解决了 “凑够 k 个” 的约束

C++:

#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;

vector<int> smallestSubsequence(vector<int>& a, int k) {
    int n = a.size();
    // 统计每个数字剩余出现的次数
    unordered_map<int, int> count;
    for (int num : a) {
        count[num]++;
    }

    vector<int> stack;
    // 记录栈中是否已经包含某个数字
    unordered_map<int, bool> inStack;

    for (int num : a) {
        // 每遍历一个数字,该数字剩余出现次数减 1
        count[num]--;

        // 如果数字已经在栈中,跳过
        if (inStack[num]) continue;

        // 维护单调栈的字典序最小性质
        while (!stack.empty() && stack.back() > num && count[stack.back()] > 0) {
            inStack[stack.back()] = false;
            stack.pop_back();
        }

        stack.push_back(num);
        inStack[num] = true;

        // 当栈的大小达到 k 时,提前终止(已经找到结果)
        if (stack.size() == k) break;
    }

    return stack;
}

int main() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    vector<int> result = smallestSubsequence(a, k);

    for (int i = 0; i < k; i++) {
        cout << result[i];
        if (i != k - 1) {
            cout << " ";
        }
    }
    cout << endl;

    return 0;
}

Java:

import java.util.*;

public class SmallestSubsequence {
    public static List<Integer> smallestSubsequence(int[] a, int k) {
        int n = a.length;
        // 统计每个数字剩余出现的次数
        Map<Integer, Integer> count = new HashMap<>();
        for (int num : a) {
            count.put(num, count.getOrDefault(num, 0) + 1);
        }

        Deque<Integer> stack = new ArrayDeque<>();
        // 记录栈中是否已经包含某个数字
        Map<Integer, Boolean> inStack = new HashMap<>();

        for (int num : a) {
            // 每遍历一个数字,该数字剩余出现次数减 1
            count.put(num, count.get(num) - 1);

            // 如果数字已经在栈中,跳过
            if (inStack.getOrDefault(num, false)) {
                continue;
            }

            // 维护单调栈的字典序最小性质
            while (!stack.isEmpty() && stack.peekLast() > num && count.get(stack.peekLast()) > 0) {
                inStack.put(stack.peekLast(), false);
                stack.pollLast();
            }

            stack.offerLast(num);
            inStack.put(num, true);

            // 当栈的大小达到 k 时,提前终止(已经找到结果)
            if (stack.size() == k) {
                break;
            }
        }

        return new ArrayList<>(stack);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int k = scanner.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = scanner.nextInt();
        }

        List<Integer> result = smallestSubsequence(a, k);

        for (int i = 0; i < k; i++) {
            System.out.print(result.get(i));
            if (i != k - 1) {
                System.out.print(" ");
            }
        }
        System.out.println();
    }
}

Python:

from collections import defaultdict

def smallest_subsequence(a, k):
    n = len(a)
    # 统计每个数字剩余出现的次数
    count = defaultdict(int)
    for num in a:
        count[num] += 1

    stack = []
    # 记录栈中是否已经包含某个数字
    in_stack = defaultdict(bool)

    for num in a:
        # 每遍历一个数字,该数字剩余出现次数减 1
        count[num] -= 1

        # 如果数字已经在栈中,跳过
        if in_stack[num]:
            continue

        # 维护单调栈的字典序最小性质
        while stack and stack[-1] > num and count[stack[-1]] > 0:
            in_stack[stack[-1]] = False
            stack.pop()

        stack.append(num)
        in_stack[num] = True

        # 当栈的大小达到 k 时,提前终止(已经找到结果)
        if len(stack) == k:
            break

    return stack

if __name__ == "__main__":
    import sys
    input = sys.stdin.read().split()
    idx = 0
    n = int(input[idx])
    idx += 1
    k = int(input[idx])
    idx += 1
    a = []
    for i in range(n):
        a.append(int(input[idx]))
        idx += 1

    result = smallest_subsequence(a, k)

    for i in range(k):
        print(result[i], end="")
        if i != k - 1:
            print(" ", end="")
    print()

第二题:01串划分

小钟有一个长度为 n 的 01 串 s(仅由字符 0 和 1 组成 ),另外还有 m 个数字,分别用 a₁, a₂, ..., aₘ 表示。小钟想知道,能否选择 m 个不相交的区间 [l₁, r₁], [l₂, r₂], ..., [lₘ, rₘ],使得对于任意的 aᵢ,其二进制表示(没有前导 0,0 的二进制表示就是 0 ),都能用 s 的某个连续子串 s[lⱼ, lⱼ + 1, ..., rⱼ] 来表示。

输入描述

输入包括多组测试数据:第一行输入一个正整数 T(1 ≤ T ≤ 20),表示测试数据的组数。每组测试数据的第一行有两个整数 n(1 ≤ n ≤ 100)

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

11-18 21:04
已编辑
华中科技大学 前端工程师
一共四面,进度挺快,希望能开高一点timeline:10.20&nbsp;一面&nbsp;50min10.22&nbsp;二面&nbsp;40min10.28&nbsp;hr面&nbsp;50min&nbsp;&nbsp;秒过约10.30主管面但是因为种种原因一直改时间到11月11.11&nbsp;主管面&nbsp;&nbsp;50min一面:简历拷打20min,主要是实习业务和微前端框架,然后是八股:react&nbsp;hooks,有哪些,怎么用,useEffect和useEvent区别,useMemo和react.memo区别,为什么不能在条件里用浏览器css和js和dom的解析具体过程,谁先谁后表格缓存怎么做,首屏加载怎么监控的,虚拟表格实现原理,怎么做表格选型的平时怎么使用ai,有哪些心得怎么看待ai手撕忘了,应该不是特别难的不然我会记得p.s&nbsp;&nbsp;面试官好有礼貌,唯一一个称呼为您的,答错了会有正确解答,最后问我还有什么简历没问的我还以为是我没啥能问的二面:1.受到ddos攻击后有哪些应对方案2.前端安全用过哪些3.webpack配置过什么,有用过什么插件4.树摇原理5.react和vue区别6.为什么要微前端改造7.微前端隔离的原理,快照和proxy的优缺点8.服务器部署原理,回滚原理这个的手撕也忘了,没印象就是不太难三面hr面:hr挺好的,没有压力1.个人经历询问2.为什么跑路了实习3.觉得最有成就感的事情4.有没有主导过项目5.三个词语形容自己&nbsp;&nbsp;为什么这么说6.现在最想提升的方面7.为什么选AI初创不选大厂8.对AI的看法四面主管面:拖了好久才来面,还以为不想要我了一眼看出来是字节出来的,之前的同事都是这种高效礼貌疏离的1.讲讲你实习的优化的具体2.有没有什么沟通协作的经历3.形容自己有领导力的原因4.除了想要提升技术还有什么软素质想要提升5.其他offer&nbsp;意向城市6.反问业务,是根据base地和个人倾向决定
查看27道真题和解析
点赞 评论 收藏
分享
1.项目介绍2.js有哪些数据类型3.JS&nbsp;是单线程的,那为啥还能异步,我setTimeout放在Promise后面它为啥最后才执行4.微任务和宏任务都有哪些,浏览器和Node环境下任务队列是一样的吗?有没有区别5.假如现在有一个异步链一个async函数里面用了setTimeout、Promise、await、MutationObserver你能告诉我他们的执行顺序吗6.说一下JS&nbsp;的闭包7.在一个for循环里绑定了多个按钮点击事件,结果所有点击都打印同一个值为什么,怎么来修复8.如果我写个函数里var、let、const都用了,执行顺序会怎样9.如果我把一个对象的方法当成参数传出去再执行,会发生什么10.有一个页面,它加载特别慢,你该怎么排查11.你知道浏览器是多进程的是吧,如果我打开一个新tab,是新进程还是新线程?那页面崩了会不会影响其他tab12.项目中遇到一个跨域问题,接口访问正常但是前端拿不到数据,options请求也没有,原因可能是什么?你怎么排查13.用户刷新页面,有哪些缓存是会失效的14.你在xx系统中封装了弹窗组件,那我问你:如果这弹窗还要支持拖拽自定义footer、异步确认,怎么设计15.组件通信方式你都了解哪些?从父子到兄弟再到非嵌套组件全局通信Vue和React&nbsp;的做法有区别吗16.现在给你一个数组里面全是整数但有一对数之和等于某个目标值你得返回所有满足条件的下标对,而且不能重复,你怎么写时间复杂度控制在O(n)以内17.现在有个嵌套JSON比如树状结构的菜单,里面包含任意层级的children,你能不能写个函数把它扁平化展开成一个平铺数组18.给你一个DOM树让你从根节点遍历,把所有节点的tagName&nbsp;打印出来你会怎么做20.你现在在页面上使用fetch请求xx的一个接口,服务端没加&nbsp;CORS&nbsp;header,结果你用Postman却能正常访问,为什么22.手撕:使用JS实现一个repeat方法function&nbsp;repeat&nbsp;(func,&nbsp;times,&nbsp;wait)&nbsp;{},​const&nbsp;repeatFunc&nbsp;=&nbsp;repeat(alert,&nbsp;4,&nbsp;3000),&nbsp;调用这个repeatedFunc("hellworld")会alert4次helloworld,&nbsp;每次间隔3秒
点赞 评论 收藏
分享
评论
3
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务