远景智能的秋招笔试,说实话在投递之前我就听师兄提过一嘴:题量不小、覆盖面广、而且不只是考算法,Java、Linux、数据结构这些基础会揉在一起出。2023秋季招聘软件技术笔试题(第二批)我是在截止前一周才做的,整体感受是——它不像很多大厂那样搞几道hard算法定生死,而是更在意你能不能把基础知识讲清楚、用明白。尤其是那些看起来平平无奇的题目,背后藏着的坑特别深。这篇文章我就把整套卷子的结构、考点分布、典型题型和我的复盘过程完整写出来,给后续要投递的同学一个参考。
1. 整套笔试题的卷面结构与考察逻辑
1.1 题型占比与时间分配的实战判断
第二批笔试题的卷面大致分四个部分:单项选择、多项选择、填空、两道编程题。总时长90分钟,我实测下来时间相当紧张——前面选择填空大约50题,编程题虽然只有两道,但第二道题涉及状态设计和边界处理,不提前规划时间很容易做不完。
从占比来看,选择题和填空题覆盖了Java语法、数组与指针、Linux命令、网络基础、数据库SQL,大概占了70%的分值;两道编程题占30%。这里有个容易被忽略的点:选择题并不是单纯选答案,有些多选题会故意设计成"完全正确"和"不完全正确"的干扰项,稍不注意就会多选或少选。我统计了一下,多选题的分值占比大概在20%左右,但错误率比单选高了不少。
时间分配上,我的建议是前40分钟解决所有选择和填空,留30分钟给第一道编程题,最后20分钟处理第二道编程题。如果你第一道编程题预计要写40分钟以上,第二道就用最朴素的办法拿部分分。远景智能的这套题不按单题给分,而是按整体正确率划线,所以牺牲一道编程题去保证选择题正确率,往往比硬磕两道题都半成品要划算。
1.2 从岗位描述反推考点:他们到底想招什么样的人
投递远景智能软件技术岗的同学,JD上会明确写"熟悉Java/Python、了解Linux、有数据结构与算法基础"。但笔试的考点分布比JD暗示的更聚焦——它考察的核心其实是两个能力:第一,你能不能在没有IDE和搜索引擎的环境下写出逻辑严密的代码;第二,你对于运行机制的理解是否停留在"会用API"的层面。
举个例子,填空题里有一道关于Java中HashMap在JDK8之后链表转红黑树的阈值问题。如果只是背过"8"和"64"这两个数字,这道题也能答,但它紧接着又考了一道"为什么是树化阈值8、最小容量64"的简答。这就是典型的"知道你背过,但更想知道你懂不懂背后的泊松分布和哈希冲突概率模型"。这反映到筛人逻辑上就是:他们宁可要一个基础扎实、能推断出结论的人,也不要一个只会背面试题锦集的人。
这一点和热词里提到的"java笔试题大全带答案"那种刷题思维完全不同。远景的题很少出现网上流传的原题,更多是把基础概念换一个包装场景,比如把数组和指针的题目套到一段多线程共享数据的代码里,让你判断最终输出。如果你只背了静态的结论,碰到这种动态场景很容易翻车。
2. 数组和指针:Java与C/C++的边界题才是重头戏
2.1 一道"看似简单"的指针选择题,坑在数组名退化
热词里"数组和指针笔试题"被搜得很频,远景第二批确实考了这类题,但问法比一般刷题网站刁钻。它给了一段C++代码,声明int arr[5],然后问sizeof(arr)、sizeof(&arr[0])、sizeof(*arr)、sizeof(arr+1)的值分别是多少。如果你只记过"数组名是首地址",很容易把后两个也填成4或8。
实际上,sizeof(arr)是整个数组的大小,也就是20字节;sizeof(&arr[0])是指针大小,在64位系统上是8;sizeof(*arr)是arr[0]的大小,4;而sizeof(arr+1)虽然写法上看起来像野指针,但这里arr作为右值发生了数组到指针的退化,所以结果是8。这个知识点考的不是你会不会算,而是你清不清楚数组名在什么场景下会退化成指针、什么场景下会保留数组类型。
我当时做题时就在这上面停了一分钟,因为四个空连在一起,很容易模式化地把前两个填对之后,后两个顺手就填错了。这里的一个实操经验是:遇到数组和指针混合的题目,先圈出"取地址符"和"sizeof括号里的表达式有没有发生求值",sizeof里的表达式不参与真正的运行期计算,只做类型推导。
2.2 Java引用传递的经典误解:值传递还是引用传递
Java部分的数组和指针题,其实考的是引用传递的理解。题目大概是这样:定义一个方法void change(int[] arr),方法内执行arr[0] = 100,然后在main里新建数组arr = {1,2,3}并调用change(arr),问最终arr[0]的值。这道题80%的人都能答对是100,但它紧接着问:如果在方法内执行arr = new int[]{7,8,9},外部数组变不变?
答案是外部数组不变。因为Java的arr是一个引用,传递的是引用的拷贝,所以你在方法内重新赋值只是让拷贝指向了新对象,原引用不受影响。这个知识点本身不冷门,但远景把两道题放在一起考,就是想筛选出那些真正理解"引用是一个变量,它的值是地址"的人,而不是只记住"数组是引用传递"这句话的人。
这里我补充一个自己的调试经验:如果你对方法内的数组修改是否会影响到外部有疑惑,不需要去硬记"值传递"还是"引用传递",直接在change方法第一行打印arr.hashCode(),在调用方再打印一次。如果两次打印的哈希值一致,说明引用指向同一个对象,那对内容的修改自然会反映出来;如果方法内重新new了数组,哈希值就会变,外部不受影响。这种验证方式放在笔试阶段也可以用来做心理检查:如果一个题目的代码片段没有new,那所有对内容的修改都是对原对象生效的。
2.3 字符串与字符数组:隐藏的"不可变性"考点
字符串相关的坑在远景笔试里也占了几个选择题。比如它问:String s = "hello"; s += "world";这个过程创建了几个对象?很多人会答2个,但实际上是3个——"hello"一个、"world"一个、"helloworld"一个。如果再算上字符串常量池里的引用,可能更多。这道题考察的是String的不可变性,以及字符串拼接在底层是创建StringBuilder还是直接创建新对象的问题。
更进阶的版本是混合String和StringBuilder的题目。它给出一段代码,用StringBuilder拼接,然后问toString()之后和直接用+拼接有没有区别。答案是没区别,因为+在编译期就会优化成StringBuilder.append()。但如果拼接发生在循环里,并且每次循环都产生新的StringBuilder,那性能就会断崖式下降。这类题的判断方法很简单:看变量是否在循环体内声明,如果声明在循环内,那每次迭代都会创建新对象,即使逻辑正确也会被面试官追问性能优化。
3. Linux与系统编程:考察的不只是命令,而是"系统观"
3.1 文件描述符与重定向:一道命令题背后的进程模型
远景笔试的Linux部分,热词里"linux笔试题"搜得很多,但实际考法比常见的"说出chmod权限"要深入得多。它考了一道关于重定向的填空题:在shell中执行cat file1.txt > file2.txt 2>&1,如果file2.txt不存在,系统会显示什么?这道题看似是考命令,实际上考三件事:标准输出和标准错误的区别、重定向符号处理顺序、文件描述符的指向。
关键在于2>&1把标准错误重定向到了当前标准输出的目标——也就是file2.txt。但这里有个顺序陷阱:如果写成cat file1.txt 2>&1 > file2.txt,那标准错误会先指向终端,然后再把标准输出重定向到文件,最终错误信息还是会打到终端上。这个顺序问题如果不实际操作,光靠背结论很容易搞混。我当时做的时候,就先把>理解成"左边是旧内容、右边是新内容"的赋值操作,在草稿纸上画了文件描述符的指向图,最后才判断清楚。
如果你在笔试前想突击这个知识点,我给你一个最稳妥的记忆锚点:从左到右依次解释重定向,每一步都站在"当前shell进程的文件描述符表"角度去理解。标准输入是0,标准输出是1,标准错误是2,>file就是让1号描述符指向这个文件,2>&1就是让2号描述符指向1号当前指向的地方。顺序不同,第一步改变的描述符就不同,最终的结果自然不同。
3.2 进程、管道与僵尸进程:系统编程基础题
Linux部分还有一道综合题,考的是fork()和管道。题面大致是:父进程创建一个管道,然后fork()一个子进程,子进程往管道写数据,父进程从管道读数据,问如果不关闭管道的读端会发生什么?这个题目的答案是"父进程会一直阻塞在read()上",因为管道有数据可读时read返回,没数据时会阻塞等待写入端关闭。如果写端一直不关闭(子进程没退出或子进程也继承了写端),读端就永远等不到EOF。
这道题的隐藏考点是:fork()之后,子进程会复制父进程的文件描述符表,所以管道有两个写端——父进程的和子进程的。即使子进程写完之后退出,父进程的写端还开着,read()仍然不会返回EOF。正确的做法是父进程把自己的写端也关掉,只保留读端。这个话题在笔试里不会要求写完整代码,但会考你填空"父进程应该关闭___端",以及判断某个操作后会发生什么。
这一题我建议所有准备笔试的同学都自己在本地跑一次。代码量不多,大概十几行,但运行结果会给你非常直观的体感。很多系统编程的题,比如僵尸进程的产生原因和waitpid的作用,都可以用这种"自己写一个不回收子进程的父进程,然后ps -el看状态为Z"的方式去理解。笔试只是结果,你真正要建立的是一套"进程生命周期"的系统观。
3.3 网络排查里的Linux考点:从ping到traceroute
网络基础的部分,远景笔试和Linux命令做了结合。它给了若干条命令,让你选出哪一个可以查看本机监听的TCP端口。ping是ICMP探测,netstat -tlnp才能看监听,traceroute是看路由路径,ifconfig是看网卡配置。这题本身不难,但它的意义在于提醒你:实际项目里排查网络问题,光会ping是远远不够的。
如果你以后做分布式或物联网方向,类似"连接超时排查"的思路可以提前储备一下:先用ping确认网络通不通,再用telnet ip port确认目标端口通不通,接着用traceroute看哪一跳延迟异常,最后用tcpdump抓包看有没有重传。这些其实都不是特别高深的命令,但笔试把它们放在一起考,说明岗位日常开发中很可能要跟设备、网络打交道,系统级的排查能力是刚需。
4. 算法与数据结构题目:难度适中,但边界条件和设计感很重
4.1 第一道编程题:字符串相关,双指针技巧与复杂度分析
第一道编程题我印象比较深,题目是"给定一个字符串,找出最长无重复字符子串的长度"。这道题在LeetCode上是第3题,本身不冷门,但远景给了一个额外的限制:字符串中不仅包含字母,还包含数字和特殊字符,要求你写时考虑字符集可能很大的情况,不能假设只有26个小写字母。
这道题最标准的解法是滑动窗口加哈希表。我用一个HashMap<Character, Integer>记录每个字符最近一次出现的索引,然后用left指针维护窗口的左边界。遍历到某个字符时,如果它已经在哈希表里且索引不小于left,就把left移动到上次出现位置的下一个;否则窗口就能继续扩大。每次计算right - left + 1更新结果。时间复杂度O(n),空间复杂度O(min(字符集大小, n))。
这里我想强调一个容易扣分的点:很多人在笔试里会直接写"假设只有小写字母",然后用一个长度为26的数组代替哈希表。如果题目没有明确说明字符集范围,这种假设是有风险的。我写的时候就按照"任意ASCII字符"来考虑,虽然代码稍微多几行,但能体现你考虑到了题目隐含的边界。笔试阅卷很多时候会看注释和思路,而不是只跑测试用例。
4.2 第二道编程题:带过期时间的缓存设计,如何用数据结构组合实现
第二道编程题的分值更高,题目类似"设计一个带有过期时间的KV缓存,支持get和put操作,并且在get时如果key已过期则视为不存在"。这道题说难不难,说简单也不简单,因为它考察的不是某个孤立算法,而是数据结构的组合能力。
我的做法是:用一个HashMap存key到value以及过期时间的包装对象,再用一个优先队列(小顶堆)来维护每个key的过期时间。put时插入到map和堆中;get时先从堆顶弹出所有已经过期的key,再检查map中是否存在目标key。这样做的好处是:过期key的清理只需要在插入和查询的时机进行,时间复杂度依然是O(logn)级别,最坏情况也就是每轮弹出若干个过期项。
但这里有一个隐藏的坑:如果同一个key被多次put,堆里会存在多个不同过期时间的相同key。我在弹堆顶时需要判断当前堆顶的过期时间是否等于map中该key的过期时间,如果不是,说明这是旧数据,直接弹出忽略。如果不加这个判断,很可能会在get一个没过期的key时,因为堆顶是同一个key的早过期版本而误删。这个细节我是在写完后自己走了一遍测试用例才发现的,如果笔试时时间紧,很容易漏掉。
这道题反映出来的思路是:远景对算法题的考察不只是"会不会写某个模板",而是"能不能在模板基础上做变通"。优先队列加哈希表并不是什么冷门组合,但能结合过期逻辑处理干净的人并不多。如果你的目标是这类公司,建议把常考的设计题,比如LRU缓存、LFU缓存、带过期时间的缓存,都亲手写一遍,重点练"组合数据结构处理工程问题"的感觉。
4.3 数据结构基础填空题:从B+树到HashMap的冲突处理
除了编程题,数据结构部分的选择填空也不少。特别是B+树的非叶子节点不存储数据只存储索引、叶子节点用链表串起来这些特性,在笔试里出现了两次。远景的考法是把B+树和InnoDB索引做结合,问"为什么数据库索引适合用B+树而不是AVL树"。这个问题的标准答案是:B+树高度更低,且叶子节点链表便于范围查询,但如果你只答了"矮",没答"范围查询"和"磁盘IO次数少",就会被判定为不完整。
HashMap的冲突处理也考了一道,问的是"JDK8之前用链表解决冲突,JDK8之后引入红黑树的条件是什么"。这道题的考点不只是阈值8和最小容量64,还包括"哈希桶中的元素是相互独立事件还是相关事件"——官方注释里提到泊松分布。我当时在答案里写了"当哈希函数足够随机时,桶中元素个数到8的概率极低,但一旦超过8说明哈希函数可能有问题,用红黑树来缓解极端情况",这样的回答能顺带展示理解深度。
5. 从这套题反推:你应该怎么准备,才能避开最常见的坑
5.1 选择题的选项设计与"多选变单选"陷阱
这套笔试题里真正拉分的,其实是多选题。我观察到一个规律:几乎每一道多选题都有一个"听起来完全正确但表述夸张"的选项,比如"Java的垃圾回收会立即回收不再使用的对象""Linux的rm命令删除的文件一定无法恢复"。这种选项如果你不确定,最好的策略是不选。因为多选题的计分规则通常是"多选错选不得分,少选按比例得分"——我不知道远景第二批是否完全如此,但很多笔试都采用这种规则。
所以实际操作上,我在做多选题时会把"没把握的选项"当作"错误选项"处理,只保留那些能百分百确认的选项。这听起来有点保守,但对于保证整体正确率非常有效。你想想,单选错一题丢一分,多选错一题可能丢两到三分,而且多选题往往集中在Java和Linux这两个板块,这些板块的正确率对最终的筛选结果影响很大。
5.2 边界测试与读题仔细程度:编程题最容易踩的隐性坑
编程题的隐性坑主要集中在边界条件上。第一道字符串题目,如果字符串为空,我的滑动窗口应该直接返回0;如果字符串只有一个字符,应该返回1。这些看起来很简单,但一定不要在笔试里跳过去。有的同学喜欢先写主逻辑再补边界,我建议反过来:先把边界的if判断写好,再写核心逻辑,这样就不会出现"主逻辑跑通了但空输入报异常"的情况。
更值得提的是读题。远景的第二道编程题的题面里有一个小陷阱:它说"过期时间以毫秒为单位,为每个key单独设置"。如果你没注意"每个key单独设置",很容易默认所有key共用一个全局过期时间,然后设计出一个完全错误的数据结构。这是笔试非常经典的失分点——不是不会,而是没看清。我的习惯是:读题时拿笔圈出每个数字和限定词,特别是"每个""单独""最多""不超过"这些词,然后用自己的话把题目重述一遍再开始写。
5.3 从笔试到面试的复盘方法:哪些知识点大概率会被追问
如果你笔试顺利通过,接下来就是面试环节。远景的面试官通常会拿着笔试题的答题记录来问,特别是那些你答错或答得不完整的地方,所以考完一定要复盘。
我在笔试结束后花了大约一小时,把所有不确定的题目整理成了三个清单:一是"完全不会"的,二是"会但答错"的,三是"会且答对"的。重点分析第二类,因为这类通常代表你有一个"自以为理解了"的盲区。比如我当时就对2>&1这个重定向顺序特别模棱两可,虽然最后选对了,但我知道自己是蒙的。考完后我不仅补了重定向的知识,还连带复习了shell里文件描述符的继承规则,后来面试时果然被问到了类似的场景。
另外一个复盘技巧是:把题目里出现的所有"为什么"问题单独摘出来,用STAR法则写成一段面试回答。比如"HashMap为什么用红黑树"“为什么树化阈值是8”“Linux下如何排查端口占用”,这些问题既可能是笔试原题,也很可能是面试官追问的素材。提前准备好结构化的回答,比临场发挥要稳得多。
6. 写在最后:这类笔试的真正价值不是"刷过去",而是"查漏补缺"
远景智能这套2023秋季招聘软件技术笔试题(第二批),对我来说更像是一次"基础知识的全面体检"。它没有特别偏难怪的算法,也没有需要背大量框架API的题,它的每一道题几乎都在围绕"你对底层机制的理解深度"来设计。哪怕你最后不投远景,我也建议你按照类似的维度去做一次自测:Java集合的底层结构、Linux文件描述符与进程模型、数组和指针在不同语言中的差异、经典算法题的边界处理——这些几乎是大厂笔试通用的考点。
我个人还有个体会是,笔试准备不要太依赖现成的题库。像热词里的"java笔试题大全带答案"这类资料,可以用来看考点范围,但如果你只背答案,碰到远景这种包装过的题目,会非常别扭。与其花时间背三五十道题,不如把HashMap源码、常见Linux命令的底层语义、三五种经典数据结构的设计思想弄明白。笔试只是敲门砖,真正帮你走到最后的,是你对"计算机系统如何运作"这件事的扎实理解。
最后分享一个小技巧:笔试前最好自己在一台Linux机器上把fork、管道、重定向、netstat这些命令都跑一遍,不需要多深入,只要把现象和原理对应上就行。很多笔试题目你光看文字觉得抽象,但只要脑子里有一个"实际跑起来的样子",选起答案来会果断很多。祝准备笔试的各位顺利,把这套题里的经验转化成自己的知识网络,后面不管去哪家,都会省力不少。