news 2026/7/3 15:43:05

C/C++数组与字符串高频面试题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C/C++数组与字符串高频面试题

题目 1:移除有序数组中的重复元素

题目描述

给定一个升序排列的数组nums,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。不要使用额外的数组空间,必须在原地修改输入数组并在使用 O (1) 额外空间的条件下完成。

解题思路

采用快慢双指针法:

  • 慢指针slow指向当前已去重数组的最后一个位置
  • 快指针fast遍历整个数组
  • nums[fast]nums[slow]不相等时,说明遇到了新元素,将慢指针后移一位,把快指针的值复制到慢指针位置
  • 最终慢指针索引 + 1 就是去重后的数组长度

代码实现

cpp

运行

int removeDuplicates(vector<int>& nums) { if (nums.empty()) return 0; int slow = 0; for (int fast = 1; fast < nums.size(); fast++) { if (nums[fast] != nums[slow]) { slow++; nums[slow] = nums[fast]; } } return slow + 1; }

复杂度分析

  • 时间复杂度:O (n),仅遍历数组一次
  • 空间复杂度:O (1),原地修改,无额外空间开销

面试考点

双指针思想是数组题的核心技巧,面试官常延伸问:如果允许每个元素最多出现 2 次怎么改?只需将判断条件改为nums[fast] != nums[slow-1]即可。


题目 2:旋转数组

题目描述

给定一个数组,将数组中的元素向右移动k个位置,其中k是非负数。要求使用空间复杂度 O (1)的原地算法解决。

解题思路

经典三次反转法,无需额外空间:

  1. 先反转整个数组
  2. 反转前 k 个元素
  3. 反转后 n-k 个元素 注意:k 可能大于数组长度,需要先对 k 取模k %= n

代码实现

cpp

运行

void reverse(vector<int>& nums, int left, int right) { while (left < right) { swap(nums[left], nums[right]); left++; right--; } } void rotate(vector<int>& nums, int k) { int n = nums.size(); k %= n; reverse(nums, 0, n - 1); // 反转整个数组 reverse(nums, 0, k - 1); // 反转前k个 reverse(nums, k, n - 1); // 反转后n-k个 }

复杂度分析

  • 时间复杂度:O (n),每个元素被反转两次,总操作次数为 2n
  • 空间复杂度:O (1),原地操作

面试考点

考察数组的原地操作技巧。面试官常追问:向左旋转怎么实现?如果用额外数组怎么写?对比不同方案的时空开销。


题目 3:最长公共前缀

题目描述

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串""

解题思路

纵向扫描法: 以第一个字符串为基准,逐字符检查其他所有字符串在该位置是否相同,遇到不同字符或某字符串提前结束时停止,返回当前前缀。

代码实现

cpp

运行

string longestCommonPrefix(vector<string>& strs) { if (strs.empty()) return ""; // 以第一个字符串为基准 for (int i = 0; i < strs[0].size(); i++) { char c = strs[0][i]; // 检查其他所有字符串的第i位 for (int j = 1; j < strs.size(); j++) { // 其他字符串长度不足i,或字符不相等 if (i == strs[j].size() || strs[j][i] != c) { return strs[0].substr(0, i); } } } return strs[0]; }

复杂度分析

  • 时间复杂度:O (m*n),m 是字符串平均长度,n 是字符串数量
  • 空间复杂度:O (1)

面试考点

考察字符串边界处理能力。延伸问法:用分治法怎么实现?字典树(Trie)解法的优劣?


题目 4:两数之和

题目描述

给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,且同一个元素不能重复使用。

解题思路

哈希表一次遍历法: 遍历数组时,用哈希表存储「元素值 → 索引」的映射。对于当前元素nums[i],检查target - nums[i]是否在哈希表中:

  • 存在:直接返回两个索引
  • 不存在:将当前元素和索引存入哈希表,继续遍历

代码实现

cpp

运行

vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> hash; for (int i = 0; i < nums.size(); i++) { int complement = target - nums[i]; if (hash.count(complement)) { return {hash[complement], i}; } hash[nums[i]] = i; } return {}; }

复杂度分析

  • 时间复杂度:O (n),仅遍历一次,哈希表查找为 O (1)
  • 空间复杂度:O (n),哈希表最多存储 n 个元素

面试考点

考察空间换时间的优化思想。面试官常对比:暴力法 O (n²)、排序 + 双指针法、哈希表法三种方案的优劣与适用场景。


文档 2:链表专项面试题

题目 1:反转单链表

题目描述

给你单链表的头节点head,请你反转链表,并返回反转后的链表。分别用迭代和递归两种方式实现。

解题思路

迭代法(三指针): 用三个指针prevcurrnext遍历链表,逐个改变节点的 next 指向,最终 prev 成为新的头节点。

递归法: 递归反转当前节点之后的子链表,然后将当前节点的下一个节点的 next 指向当前节点,当前节点的 next 置空。

代码实现

cpp

运行

struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {} }; // 迭代法 ListNode* reverseList(ListNode* head) { ListNode* prev = nullptr; ListNode* curr = head; while (curr) { ListNode* next = curr->next; // 保存下一个节点 curr->next = prev; // 反转指针 prev = curr; // prev后移 curr = next; // curr后移 } return prev; } // 递归法 ListNode* reverseList(ListNode* head) { if (!head || !head->next) return head; ListNode* newHead = reverseList(head->next); head->next->next = head; head->next = nullptr; return newHead; }

复杂度分析

  • 迭代法:时间 O (n),空间 O (1)
  • 递归法:时间 O (n),空间 O (n)(递归栈开销)

面试考点

链表基础必考题。面试官常延伸:反转链表的前 k 个节点?反转指定区间内的链表?

谢谢
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/3 15:38:17

utzip开发者指南:从Fork到PR,参与开源项目贡献的完整流程

utzip开发者指南&#xff1a;从Fork到PR&#xff0c;参与开源项目贡献的完整流程 【免费下载链接】utzip utzip is a refactoring of zip. 项目地址: https://gitcode.com/openeuler/utzip 前往项目官网免费下载&#xff1a;https://ar.openeuler.org/ar/ 想要为utzip这…

作者头像 李华
网站建设 2026/7/3 15:36:52

如何快速部署 Compass-CI 集群?完整指南助你30分钟上手

如何快速部署 Compass-CI 集群&#xff1f;完整指南助你30分钟上手 【免费下载链接】compass-ci Compass-CI 是一个可持续集成的开源软件平台。为开发者提供针对上游开源软件&#xff08;来自 Github, Gitee, Gitlab 等托管平台&#xff09;的测试服务、登录服务、故障辅助定界…

作者头像 李华
网站建设 2026/7/3 15:34:25

LV3296与MK20DX128VFM5芯片组合的硬件设计与优化

1. LV3296与MK20DX128VFM5芯片组合的硬件定位 LV3296是一款高性能信号调理芯片&#xff0c;常被用于传感器接口和模拟信号处理场景。其典型特性包括&#xff1a; 支持10V的宽电压输入范围 内置可编程增益放大器&#xff08;PGA&#xff09; 集成24位Σ-Δ ADC 提供SPI/I2C数…

作者头像 李华
网站建设 2026/7/3 15:26:34

终极免费解决方案:3分钟永久激活你的IDM下载管理器

终极免费解决方案&#xff1a;3分钟永久激活你的IDM下载管理器 【免费下载链接】IDM-Activation-Script-ZH IDM激活脚本汉化版 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script-ZH 还在为Internet Download Manager&#xff08;IDM&#xff09;的30…

作者头像 李华
网站建设 2026/7/3 15:23:32

终极指南:NonSteamLaunchers如何让Steam Deck变身全能游戏平台

终极指南&#xff1a;NonSteamLaunchers如何让Steam Deck变身全能游戏平台 【免费下载链接】NonSteamLaunchers-On-Steam-Deck Installs the latest UMU/GE-Proton and Non Steam Launchers under 1 Proton prefix folder and adds them to your steam library. Installs... Ba…

作者头像 李华