
远景智能2023秋季招聘软件技术笔试题第二批这块我最近刚好把整套卷子完整地刷了一遍也结合周围上岸同学的高频回忆把核心考点做了复盘。这篇文章不整虚的直接从笔试结构、考察逻辑、考点拆解到答题策略全部过一遍你如果正准备投新能源或者智能物联方向的软件岗这篇可以作为你校招笔试前的速查手册。先说清楚一件事远景智能的软件技术笔试和互联网大厂的出题风格差异挺大。互联网卷子偏重算法题海战术远景这套卷子更考验你对基础知识理解的深度以及用工程化思维解决实际问题的能力。题型分布大概是单选、多选、填空、简答加两道编程题时间跨度是两个小时。你如果之前只刷LeetCode热题 HOT 100不补基础概念的话这套卷子做起来会很别扭。1. 笔试整体设计与考察思路1.1 远景智能到底想招什么样的软件工程师在拆解具体题目之前你得先明白远景智能作为一家做智能物联操作系统、能源管理平台和智慧城市解决方案的公司他们的软件岗对候选人的核心诉求是什么。第一个关键词是业务落地能力。远景智能的软件不是纯互联网C端产品更多是面向B端和G端的能源管理平台、设备接入网关、数据采集系统。这种业务场景决定了他们需要的人必须理解数据从设备端怎么采集上来、怎么传输、怎么存储、怎么在平台上做计算和分析。所以笔试里出现大量的Linux操作、网络协议、数据库设计题目并不是为了凑题量而是这些就是他们日常开发的真实技术栈。第二个关键词是底层原理的扎实程度。我做完这套卷子最大的感受是远景的笔试题很少考“你知不知道这个API怎么调用”而是反复在考“你知不知道这个API背后是怎么实现的”。比如Java集合类他不问你HashMap怎么用他问你HashMap在JDK 8之后为什么引入红黑树、扩容阈值为什么是0.75、并发环境下会出现什么问题。这种问法直接把只会背面试题答案的人筛选掉了。第三个关键词是系统思维能力。笔试最后那道大题是一个偏系统设计的场景题给你一个设备接入的场景让你画出模块划分并说明数据流转。这种题没有标准答案但能看出你有没有全局视野能不能把零散的技术点串成一个完整方案。1.2 题型结构拆解两个小时的高压考察这套卷子的题型分布大概是这样的单选题20道、多选题10道、填空题10道、简答题4道、编程题2道。听上去题量不大但实际做起来时间非常紧张。单选和多选覆盖面很广Java基础、Linux命令、网络协议、数据库SQL、数据结构和算法都有涉及。这部分考察的是知识面的广度每道题大概只有一分钟的思考时间很多题你看到就要立刻反应出答案没有时间让你慢慢推导。多选题是这套卷子比较恶心的部分少选不得分多选也不得分你必须对每个选项都有十足的把握才能拿分。填空题考得比较细重点集中在C语言指针、Java内存模型、Linux系统调用这几个方向。比如他会给你一段C语言代码让你写出指针运算之后的结果或者给你一个Java多线程场景让你填volatile和synchronized的区别。这部分是区分度最大的区域基础不扎实的人会在填空题上大量丢分。简答题和编程题是拿分的大头。简答题通常是描述一个场景让你分析比如TCP三次握手为什么不能是两次、Redis缓存穿透怎么解决、JVM垃圾回收算法对比。编程题有两道一道偏算法通常是动态规划或者DFS/BFS一道偏工程实现比如手写一个生产者消费者模型或者实现一个带过期时间的缓存。编程题支持的语言包括Java、C、Python我建议直接用你刷题时最熟练的语言别在笔试现场尝试新语言。2. 核心考点逐个拆解与实战复盘2.1 Java基础与集合源码不只是会用要懂原理Java在远景这套笔试题里占比相当高单选、多选、简答都大量涉及。考察的重点非常集中集合类源码、并发编程、JVM内存模型。关于集合类HashMap是绝对的主角。你需要把这几条线彻底搞清楚底层数据结构从数组加链表到数组加链表加红黑树的演进过程hash寻址算法的优化逻辑扩容机制为什么是2的幂次方扩容加载因子0.75的权衡依据。我再补充一个高频考点HashMap在多线程环境下put操作可能造成CPU 100%这是JDK 7及以前版本的头插法导致的死循环问题JDK 8改成尾插法后解决了死循环但仍存在数据覆盖问题。这类问题考的是你知道这个技术方案的演进历史和你能不能说清楚每个版本改动背后的原因。并发编程方面synchronized和ReentrantLock的对比、volatile的可见性和禁止指令重排、ThreadLocal的原理和内存泄漏问题这几件事几乎是必考的。我记得有场笔试直接给了一段代码问四个线程对一个共享变量做自增操作最终结果是多少。表面是考i线程安全性实际是把原子性、可见性、有序性三个概念一次性全部带出来。你光知道要加锁远远不够你必须能解释为什么加了synchronized就能解决原子性问题为什么volatile只能保证可见性不能保证原子性。JVM这块重点在内存区域划分、垃圾回收算法和类加载机制。内存区域要能画出堆、栈、方法区以及JDK 8之后的元空间、程序计数器各自的职责还要清楚哪些区域是线程共享的、哪些是线程私有的。垃圾回收算法里CMS和G1的优缺点对比是简答题的高频素材你要能说出G1的Region划分和可预测停顿模型是怎么回事。注意远景的Java题非常爱考JDK版本演进带来的变化。比如JDK 8的接口默认方法、JDK 9的模块化、JDK 11的ZGC你最好把每个大版本的核心特性过一遍笔试里作为干扰项出现频率很高。2.2 数组与指针C语言基础不过关会死得很惨远景这套卷子里有一股清流就是考察了不少C语言的内容主要集中在数组和指针。说实话我在复习时差点忽略这块还好考前把C语言基础重新过了一遍不然填空题真的会空着交卷。指针题型的套路比较固定一维数组的数组名和指针的关系、指针数组和数组指针的区分、二级指针、指针和自增运算结合时的优先级问题。给你一段代码int a[5] {1, 2, 3, 4, 5}; int *p a; 然后问*(p)和(*p)有什么区别。这种题看似基础但很多人就是在这里翻车。你需要记住两个核心原则p是先取值再移动指针(*p)是先取值然后把这个值自增注意自增的对象是p指向的变量不是指针本身。多维数组的指针运算也是高频考点。很多人搞不清楚int a[3][4]里a、a[0]、*a、a[0][0]这几个表达式在值和类型上的区别。我教你一个粗暴记法a的类型是int(*)[4]也就是指向含有4个int元素数组的指针a[0]的类型是int**a做一次解引用后类型是int*但值上等价于a[0]。笔试的时候如果时间紧直接记住一维层面看值二维层面看类型就行。还有一个很容易被忽视的考点是内存对齐。填空题给一个结构体让你算sizeof大小稍不注意就掉坑。核心规则是结构体总大小必须是最大成员对齐数的整数倍每个成员的偏移量必须是自身对齐数的整数倍。笔试时遇到这种题老老实实画一个内存布局图把每个成员的偏移量标出来再对齐到最大对齐数基本不会错。2.3 Linux与操作系统基础命令考察覆盖面广且细节刁钻Linux命令在这套卷子里的占比高得超出我的预期。单选题至少出现五道填空题也会穿插一到两道。考察方向不是你用过哪些命令而是你在实际开发中能不能正确使用命令解决问题。文件处理命令是重灾区。ls、cd、mkdir这种基础命令一般不会直接考考的是带各种参数的组合用法。比如让你找出当前目录下一小时内修改过的所有文件用find /path -mmin -60让你查看某个进程监听的端口号用netstat -tlnp或者ss -tlnp。我觉得最阴的题是给出一个场景要求选择正确的组合命令选项里各个命令看似都能做但只有一条是效率最高且正确的。比如给脚本添加执行权限选项会有chmod 777和chmod x正确答案是chmod x因为777把不该给的权限也给了不符合最小权限原则。这类题考的就是你有没有安全意识和规范意识。文本处理三剑客grep、sed、awk是考察重点awk的使用尤其值得关注。你得至少掌握awk的字段分割默认按空格可以用-F指定、BEGIN和END块的概念、内置变量NR和NF的区别。远景有一套卷子考了这样一个场景统计日志文件里每个IP地址出现的次数用awk {count[$1]} END {for (ip in count) print ip, count[ip]} access.log。这道题如果不会awk基本只能放弃但只要你平时写脚本时真正用过awk三秒钟就能敲出来。操作系统原理方面进程和线程的区别、进程间通信方式管道、消息队列、共享内存、信号量、Socket、死锁的四个必要条件、虚拟内存和分页机制这些是简答题的常见素材。备考时不用去背操作系统教材的原文但你要能用自己的话把每个概念讲清楚最好能结合一个实际场景说明为什么需要这个机制。2.4 计算机网络与数据库应用层协议和SQL优化网络部分的考察集中在TCP/IP协议栈重点在传输层和应用层。TCP三次握手和四次挥手是必考题但远景不爱考这个过程分几步他更爱考为什么和异常情况下怎么办。比如三次握手为什么不能合并成两次第三次握手失败了会怎样SYN Flood攻击的原理和防御方式是什么四次挥手中的TIME_WAIT状态为什么要等2MSL这些为什么类的问题需要你对TCP状态机有比较深入的理解。我建议你亲手把TCP的状态迁移图画一遍不要只记图要理解每个状态切换的条件然后对着状态图去解释每个场景。比如TIME_WAIT的作用一是保证最后的ACK能到达对方如果丢了可以重传二是让旧连接的报文在网络中消逝避免影响新连接。你在理解这层逻辑后任何变化都难不倒你。HTTP协议方面重点在HTTP/1.1和HTTP/2的对比、HTTP和HTTPS的区别、常见的状态码语义。状态码是单选题常客301和302的区别、401和403的区别、500和502的区别这些一定要彻底分清。我给你一个记忆方法301和302都是重定向301是永久迁移浏览器会缓存302是临时跳转401是未认证需要登录403是已认证但无权限500是服务器内部错误502是网关收到无效响应。把这几组记牢选择基本秒答。数据库考察的特点是SQL写得多、概念题少。SQL题会让你根据表结构写查询语句涉及GROUP BY、HAVING、子查询、JOIN这些常规操作。比互联网笔试简单的地方在于不太考复杂的窗口函数但考察了索引优化。有一道简答题是让你比较聚簇索引和非聚簇索引的区别并说明什么情况下索引会失效。需要注意的索引失效场景包括在索引列上进行函数运算、隐式类型转换、LIKE以通配符开头、使用OR连接非索引列。这些是真实业务开发中很容易踩的坑也是面试官筛选候选人是否真正写过生产SQL的重要标志。2.5 编程题算法题与工程题并重编程题有两道一道是纯算法题另一道是工程实现题。算法题我遇到的是动态规划背包类问题难度对标LeetCode中等偏上。这种题目其实考核的不只是算法设计更是你的代码规范程度。代码能不能通过全部测试用例是一方面代码结构是否清晰、边界条件是否处理完整也会在人工阅卷时被考察。我的建议是算法题养成三个习惯。第一先写解题思路再做代码在答题框里用注释写下时间和空间复杂度分析第二边界条件单独处理数组为空、数组长度为1、目标值不存在这些情况在草稿纸上先列出来第三定义一个工具函数来维护状态数组提高代码可读性比如背包问题就单独定义一个solveKnapsack函数别把逻辑全堆在main里。工程题考的是经典的并发场景比如实现一个阻塞队列或者实现一个带过期时间的LRU缓存。这类题考察的是你平时写业务代码时有没有真的思考过并发控制。实现带过期时间的缓存时你需要考虑的核心问题包括用什么数据结构存储数据、过期时间如何管理与检查、多线程读写时如何保证线程安全。这种题没有唯一正确答案但阅卷人能从你的代码里看出你有没有并发编程的实战经验有没有考虑过内存泄漏、性能瓶颈这些工程问题。3. 实操过程与核心环节实现3.1 我的做题顺序与时间分配方案两个小时的笔试时间看起来充裕实际做起来非常赶。我不建议你按照试卷的题目顺序从头做到尾而是要按照“先易后难、先拿分后攻坚”的原则分配时间。我的做题策略是把时间切成四块。第一块在前15分钟内完成所有单选题遇到卡壳的题先选一个最有把握的答案并标记不在单选题上恋战。第二块用20分钟处理多选题和填空题多选题要注意宁缺毋滥拿不准的选项不要选因为少选和错选都不得分。第三块用40分钟完成四道简答题每道题控制在10分钟以内重点是把要点写全、逻辑写清晰不要展开长篇大论。最后一块留45分钟做两道编程题——算法题25分钟工程题20分钟——剩下10分钟用来检查前面标记过的题目和补充代码注释。考试系统通常支持本地IDE编译但核心运行环境还是在线OJ。我强烈建议你笔试前去牛客网熟悉一下在线答题环境尤其是代码框自动补全、缩进、输出格式这些东西。我见过太多人因为不熟悉OJ环境把输出格式搞错导致通过率为0的情况。3.2 算法题实现背包问题的两种写法远景这套卷子里我印象最深的算法题是典型的01背包变形有n个物品每个有重量和价值求背包容量为V时的最大价值。限制条件是物品数量n500背包容量V50000物品重量在1到100之间。这个数据范围说明两层意思一是数据量挺大暴力搜索会超时二是物品重量范围小的特点可以考虑优化。标准的动态规划写法其实两条思路都可以。思路一是常规的二维DP使用二维数组dp[i][j]表示前i个物品在容量j下的最大价值。复杂度是O(n*V)也就是500*500002500万勉强能过但有点悬。思路二是滚动数组优化把二维降到一维。因为dp只依赖上一行的状态所以可以从后往前遍历容量状态转移方程为dp[j] max(dp[j], dp[j - weight[i]] value[i])。从后往前遍历的目的是保证每个物品只被使用一次因为更新dp[j]时dp[j - weight[i]]还是上一轮没有放当前物品时的状态。这里我给一个可以直接用的模板代码Java写法如下public class Knapsack { public static void main(String[] args) { int n 500; int capacity 50000; int[] weight new int[n]; int[] value new int[n]; // 初始化 weight 和 value 数组 int[] dp new int[capacity 1]; for (int i 0; i n; i) { for (int j capacity; j weight[i]; j--) { dp[j] Math.max(dp[j], dp[j - weight[i]] value[i]); } } System.out.println(dp[capacity]); } }代码本身很简单但有几个细节值得提醒。dp数组初始化为0意味着每个物品可以选择不装、装部分。但如果你要求恰好装满背包dp数组除了dp[0]0之外都要初始化为一个极小负值比如Integer.MIN_VALUE / 2。这样做的原因是使得不能从非法状态转移成为唯一可能最后如果dp[capacity]仍然是负值说明无法恰好装满。这两个状态的差别我在笔试时就见过很多次大家一定要看清楚题目问的是最大价值还是恰好装满的最大价值。3.3 工程题实现手写一个带过期时间的LRU缓存这道工程题我选的实现方案是LinkedHashMap加手动过期检查。Java的LinkedHashMap底层维护了一个双向链表访问顺序模式下可以天然实现LRU的最近最少使用淘汰顺序。但是笔试里直接继承LinkedHashMap重写removeEldestEntry也行不过我更喜欢组合的方式把过期时间逻辑和LRU逻辑解耦代码可读性更高。我给出一个参考实现import java.util.concurrent.ConcurrentHashMap; public class ExpiringLRUCacheK, V { private static class CacheEntryV { V value; long expireAt; CacheEntry(V value, long expireAt) { this.value value; this.expireAt expireAt; } } private final ConcurrentHashMapK, CacheEntryV map new ConcurrentHashMap(); private final long ttlMillis; private final int maxSize; public ExpiringLRUCache(long ttlMillis, int maxSize) { this.ttlMillis ttlMillis; this.maxSize maxSize; } public V get(K key) { CacheEntryV entry map.get(key); if (entry null) { return null; } if (System.currentTimeMillis() entry.expireAt) { map.remove(key); return null; } return entry.value; } public void put(K key, V value) { if (map.size() maxSize !map.containsKey(key)) { K eldest map.keys().nextElement(); map.remove(eldest); } map.put(key, new CacheEntry(value, System.currentTimeMillis() ttlMillis)); } }注意这个实现里我用了ConcurrentHashMap来保证线程安全存储结构本身是哈希表并不是严格的LRU。如果笔试场景要求实现真正的LRU淘汰顺序你需要再引入一个双向链表可以用LinkedList加锁也可以自己写一个Node结构每次get时把节点移动到链表头部每次put时把新节点也放到头部当容量满时移除链表尾部节点。但这个简单版本已经能体现你对并发容器、过期淘汰策略的理解。讲到这块必须提醒一下在在线笔试环境里你的代码要保证可以完整运行不要只写核心方法。你需要补充必要的import和类的声明main方法可以留空但类名和方法签名要跟题目要求完全一致。这是很多选手容易忽略的类名写错直接编译失败前功尽弃。4. 常见问题与排查技巧实录4.1 我在复盘过程中踩过的坑第一个坑是单选和多选花费时间太多。我在第一轮模拟时单选做了35分钟多选题做了15分钟导致后面简答题时间严重压缩编程题几乎是赶出来的代码质量明显下降了。后来我调整了策略单选题遇到没思路的直接第一感觉选并打上标记坚决不回头。第二个坑是填空题里指针运算没注意类型转换我算出结果后跟编译结果差一位。后来养成了一个习惯所有指针题目在草稿纸上把类型先写出来再写表达式最后才算数值。这两个习惯直接让我第二次完整模拟时分数提高了不少。第三个坑比较隐蔽是编程题输出格式问题。那道工程题要求输出缓存命中率我按照平常练习都输出浮点数但OJ期望保留两位小数结果第一版通过率只有60%。交卷前我对这类题会格外注意题目描述里的输出格式部分有要求保留小数位数的必须格式化输出。如果你在牛客网上看到练习区有很多类似的格式化陷阱不要觉得这是低级错误不在乎笔试现场因为这种问题挂掉的人不在少数。4.2 高频失分点速查表我自己整理了这样一个高频失分点对照表复盘时对照检查非常有效分享给你失分点典型表现解决方案集合源码理解停留在使用层面只知道HashMap怎么用不知道底层结构自己画一遍put和get的流程图多线程只背结论不理解本质volatile和synchronized混为一谈用代码做实验验证可见性和原子性C语言指针类型混淆int*和int(*)[4]分不清把指针声明先做类型分解再分析Linux命令只会看不会用知道存在但不知道参数场景写一段日志分析脚本实际操作SQL索引失效场景不熟悉只知道有索引查询快造一万条数据实测三种失效场景编程题不处理边界条件数组为空/长度为1直接数组越界写代码前先在草稿本列边界用例时间分配失衡选择和填空耗时过多压榨编程题严格按时间切片执行定时提醒笔试环境不熟悉到笔试前才第一次用牛客提前一周每天做一套模拟题这张表如果你能对照着逐个自查其实比多刷五套卷子更有效。因为远景这种风格的笔试题丢分往往不是知识点不会而是细节和策略上的疏漏。4.3 针对性的备考建议与复习节奏根据这套卷子的考察范围考前两周的复习节奏我建议这样安排。第一周集中补基础概念的短板每天花两小时过Java集合源码和并发编程一小时做Linux命令实操一小时刷数据结构优先数组、链表、树和动态规划。第二周进入模考阶段每天严格按照考试时间做一套真题或仿真题做完之后用一小时复盘错题。此时不要再去学新知识重点是保持手感和查漏补缺。值得提醒的是针对远景的笔试风格你需要特别关注几个别人容易忽略的板块。一是C语言指针相关考点互联网公司笔试通常不怎么考但远景会考所以你在牛客上找不到太多针对性练习只能自己找C语言教材的习题来补。二是Linux命令实操不要在本地只装Windows建议在虚拟机或云服务器上装个Linux环境日常操作都迁移到终端进行这样练出来的手感才是真实可靠的。三是SQL索引优化不要只背理论建议自己建一张几万行的表执行EXPLAIN观察各种查询的执行计划把索引失效的几种情况逐一复现。如果你是非科班转码选手我额外建议你优先保证Java基础和数据结构这两块的正确率这两块在整张卷子里占比最高。网络和Linux如果时间不够可以主攻高频命令和TCP握手挥手的基本原理先把最容易出分的部分稳住。关于笔试的环境准备虽然在线笔试只用浏览器完成但最好在本地提前配好Java和Python编译环境。万一考试系统内置的编译器版本跟你本地不一致比如在线编译器是Java 8本地装了Java 17代码里面用了新特性会导致编译不过这种问题特别冤。笔试前半小时把摄像头、麦克风、网络准备好把桌面清理干净因为有的远程笔试会要求屏幕共享或者开启防切屏限制不要因为环境问题被判定违规。我个人在实际操作中的体会是远景智能这套笔试题的难度并不是顶尖水平但它的考察维度和出题角度非常有特色。它不像某些大厂那样狂堆偏难怪题而是把Java、C、Linux、网络、数据库这些计算机基础核心科目做了一个全面覆盖更看重候选人基础功底的扎实程度和应用能力。准备这种风格笔试题的时候刷题软件刷得再多也不如老老实实把基础概念吃透真正理解每个技术方案背后的设计逻辑和适用场景做题时的正确率自然就会提上来。备考最后一两天也别再做大量新题了把本篇文章里的考点拆解和那几道例题的代码自己动手重写一遍再对照速查表检查自己还有哪些薄弱环节。把基础知识和答题节奏掌握好再到考场上冷静发挥拿下面试资格是完全有机会的。