常见面试题
这里总结自己遇到过的面试问题
哎呦,帅小伙哦
这个作者很懒,什么都没留下…
展开
-
深入理解自旋锁(Spin Lock)
4、优缺点及适用场景。原创 2024-07-03 13:28:22 · 445 阅读 · 0 评论 -
理解条件变量:并发编程的利器
条件变量是一种同步原语,通常与互斥锁(Mutex)一起使用。它主要用于让一个或多个线程等待某个条件发生变化,然后被通知继续执行。条件变量提供了一种有效的方式来避免忙等待(busy waiting),从而提高程序的效率。2、条件变量的工作原理。原创 2024-07-03 13:23:39 · 354 阅读 · 0 评论 -
一篇文章了解lambda表达式的本质
其实这里就可以看出,值捕获时,编译器会把捕获到的值作为类的成员变量,并且变量是以值的方式传递的。需要注意的时,如果所有的参数都是值捕获的方式,那么生成的operator()函数是const函数的,是无法修改捕获的值的,哪怕这个修改不会改变lambda表达式外部的变量,如果想要在函数内修改捕获的值,需要加上关键字 mutable。一个lambda表达式基本上就是一个函数,但它没有名字。(备注:这里的编译的翻译结果并不和真正的结果完全一致,只是把最主要的部分体现出来,其他的像类到函数指针的转换函数均省略)原创 2024-04-18 23:58:16 · 913 阅读 · 0 评论 -
LeetCode 448 找到所有数组中消失的元素
LeetCode原创 2022-10-30 23:42:03 · 72 阅读 · 0 评论 -
LeetCode 84 柱状图中最大的矩形
LeetCode原创 2022-10-30 23:23:54 · 72 阅读 · 0 评论 -
LeetCode 1171 从链表中删去总和值为0连续节点
LeetCode原创 2022-10-17 22:29:52 · 95 阅读 · 0 评论 -
LeetCode 278 第一个错误版本
LeetCode原创 2022-10-14 20:54:58 · 112 阅读 · 0 评论 -
LeetCode 287 寻找重复数
LeetCode原创 2022-10-08 00:03:52 · 208 阅读 · 0 评论 -
LeetCode 304 二维区域和检索
前缀和原创 2022-10-07 15:40:22 · 193 阅读 · 2 评论 -
LeetCode 880 索引处的解码字符串
LeetCode原创 2022-10-07 00:42:44 · 114 阅读 · 0 评论 -
LeetCode 315 计算右侧小于当前元素的个数
每日一题原创 2022-09-15 23:36:51 · 133 阅读 · 0 评论 -
LeetCode 240 搜索二维矩阵
每日一题原创 2022-09-05 23:10:46 · 95 阅读 · 0 评论 -
STL迭代器失效问题
一、序列式容器(数组式容器)对于序列式容器(如vector,deque),序列式容器就是数组式容器,删除当前的iterator会使后面所有元素的iterator都失效。这是因为vetor,deque使用了连续分配的内存,删除一个元素导致后面所有的元素会向前移动一个位置。所以不能使用erase(iter++)的方式,还好erase方法可以返回下一个有效的iterator。for (iter = cont.begin(); iter != cont.end();){ (*it)->doSome转载 2021-10-18 17:09:02 · 222 阅读 · 0 评论 -
C++中空类的大小的几个字节
C++中空类的大小为1(面试的时候遇到过,我答不是1就是4,我猜是4,,,正确答案是1),在C++中空类会占一个字节,这是为了让对象的实例能够相互区别。具体来说,空类同样可以被实例化,并且每个实例在内存中都有独一无二的地址,因此,编译器会给空类隐含加上一个字节,这样空类实例化之后就会拥有独一无二的内存地址。如果没有这一个字节的占位,那么空类就无所谓实例化了,因为实例化的过程就是在内存中分配一块地址。注意:当该空白类作为基类时,该类的大小就优化为0了,这就是所谓的空白基类最优化。注意:空白基类最优化无法被转载 2021-10-18 16:39:46 · 1093 阅读 · 0 评论 -
LeetCode 162 寻找峰值
分析二分查找,题目给的条件是相邻节点不相同,所以当nums[mid] < nums[mid + 1]时,右边肯定有一个峰值,否则左边肯定有一个峰值。代码class Solution {public: int findPeakElement(vector<int>& nums) { int left = 0; int right = nums.size() - 1; int size = nums.size();.原创 2021-09-15 13:21:56 · 107 阅读 · 0 评论 -
判断数组中超过一半的数
分析常见面试题,排序的话复杂度太高,可以通过一个计数器nTimes来辅助。代码int findHalfMaxValue(int[] numb){ int length=numb.length; int nTimes,i,value; nTimes = 0; for(i=0;i<length;i++){ if(nTimes==0){ value=numb[i]; .原创 2021-09-13 16:45:39 · 142 阅读 · 0 评论 -
LeetCode 148 链表的归并排序
代码/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */class Solution {public: ListNode* merge(ListNode* head1, ListNode* head2){ Lis.原创 2021-09-13 16:07:25 · 71 阅读 · 0 评论 -
std::vector<bool>
std::vector这是一项专门std::vector针对空间效率(有争议)的专业化。但是,它的行为与常规相似但并不相同std::vector。这主要归因于这样的事实:std::vector它不是通常的C++标准库意义上的容器,而是一个位数组。 std::vector和常规vector之间的一些区别std::vector是:std::vector::iterator 不是随机访问迭代器.std::vector 不需要将其元素存储为连续数组.std::vector公开class std::vector原创 2021-09-02 12:04:08 · 919 阅读 · 0 评论 -
KMP算法
描述查找字符串T中有多少个字符串S,返回个数。KMP算法的改进,把next数组加一个位置。当遍历到这个位置的时候,个数加一。代码class Solution {public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 计算模板串S在文本串T中出现了多少次 * @param S string字符串 模板串 * @param T string字符串 文本串 * @return in.原创 2021-09-01 12:36:55 · 64 阅读 · 0 评论 -
C++ 移位操作
左移全部是补0,这毫无疑问!在右移操作中,最左侧补0还是补1,完全取决于操作数本身是不是符号数。如果是无符号数,则全部是补0,如果是有符号数,则补符号位上的数字,负数补1,正数补0;也就是说,对于有符号数,无论怎么移,符号位保持不变!!!...原创 2021-08-31 09:14:30 · 1043 阅读 · 0 评论 -
LeetCode 679 24点游戏
分析递归回溯,judge函数的含义是对cards中的数据做满足题目的操作是否可以得到24(添加cards.size() - 1个运算符),有顺序的取出两个数进行操作,然后把这两个数操作的结果放到新的vector里面。递归调用judge。面试高频题代码class Solution {public: bool judgePoint24(vector<int>& cards) { vector<double> vec(cards.begi..原创 2021-08-28 11:17:11 · 116 阅读 · 0 评论 -
LeetCode 54 螺旋矩阵
分析定义四个变量r0,r1,c0,c1分别代表当前可以到达的最小行,最大行,最小列,最大列。代码class Solution {public: vector<int> spiralOrder(vector<vector<int> > &matrix) { vector<int> ans; int n = matrix.size(); if(n == 0) return ans; .原创 2021-08-26 21:30:12 · 75 阅读 · 0 评论 -
常见面试题——索引最左前缀匹配原则
在面试中,经常会遇到这种问题,如果我们设置联合索引的顺序是(a, b, c), 那么如果我们在查询时的顺序却是(a, c, b) 会走索引吗?这个问题被问到的频率之高,令人乍舌,在这篇文章中,我们就深入探究一下,应该如何回答这一类问题,并且探寻他背后的原理,那就是最左匹配原则。最左前缀匹配原则:在MySQL建立联合索引时会遵守最左前缀匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。要想理解联合索引的最左匹配原则,先来理解下索引的底层原理。索引的底层是一颗B+树,那么联合索引的底层也就是一颗转载 2021-08-24 18:21:15 · 1104 阅读 · 0 评论 -
C++常见面试题(12)——二维数组按行遍历和按列遍历的区别
按行遍历效率高。对c++语言而言,数组在内存中是按行储存的,按行遍历时可以由指向数组第一个数的指针一直往下走,就可以遍历完整个数组,而按列遍历则要获得指向每一列的第一行的元素的指针,然后每次将指针指下一行,但是指针的寻址很快,所以不会有明显的区别。按行遍历比按列遍历效率高体现在哪里呢?1、CPU高速缓存:维基百科中有以下的内容:CPU高速缓存(英语:CPU Cache,在本文中简称缓存)是用于减少处理器访问内存所需平均时间的部件。在金字塔式存储体系中它位于自顶向下的第二层,仅次于CPU寄存 器。其容量转载 2021-08-24 11:30:42 · 1025 阅读 · 0 评论 -
C++常见面试题(11)——volatile
本文主要介绍在C/C++语言中,volatile关键字的相关内容。1 概述1.1 why volatilevolatile 关键词,最早出现于19世纪70年代,被用于处理 MMIO(Memory-mapped I/O) 带来的问题。在引入 MMIO 之后,一块内存地址既有可能是真正的内存,也有可能是映射的一个I/O端口。因此,读/写一个内存地址,既有可能是真正地操作内存,也有可能是读/写一个I/O设备。那么 MMIO 为什么需要引入 volatile 关键词呢?我们结合下面这段示例代码进行解释:转载 2021-08-24 11:23:17 · 508 阅读 · 0 评论 -
LeetCode 135 分糖果
分析把数据放到最小堆里面,然后依次取出进行处理,从小到大处理,一次循环就可以找出所需的最少糖果数。这个思想可以引申到小孩围成圈的情况。代码struct node{ int index; int rating;};struct fun{ //重写仿函数 bool operator()(const node& node1, const node& node2){ return node1.rating > node2.rating.原创 2021-08-23 22:57:41 · 89 阅读 · 0 评论 -
LeetCode 51 N皇后
分析这个问题的本质和全排列问题差不多,决策树的每一层表示棋盘上的每一行;每个节点可以做出的选择是,在该行的任意一行放置一个皇后。函数backtrack函数像在决策树上游走的指针,每个节点就表示在board[row][col]上放置皇后,通过isValid函数可以将不符合条件的情况剪枝。在前面的博客讲解了回溯算法的框架,其实回溯算法就是改改做选择的方式,排除不合法选择的方式而已,只要框架存于心,面对的就是小问题。代码class Solution {public: vector<vec.原创 2021-05-16 22:04:07 · 67 阅读 · 0 评论 -
回溯算法
解决一个回溯问题,实际就是一个决策树的遍历过程。只需要思考3个问题:1)路径:也就是已经做出的选择2)选择列表:也就是你当前可以做的选择3)结束条件:也就是到达决策树底层,无法再做选择的条件回溯算法的通用框架如下:result = []def backtrack(路径,选择列表): if 满足结束条件: result.add(路径) return for 选择 in 选择列表: 做选择 backtrack(路径, 选择列表); 撤销选择其核心就是for循环里面的递归原创 2021-05-16 20:11:48 · 107 阅读 · 0 评论 -
LFU算法的实现
分析我们定义两个哈希表,第一个 freq_table 以频率 freq 为索引,每个索引存放一个双向链表,这个链表里存放所有使用频率为 freq 的缓存,缓存里存放三个信息,分别为键 key,值 value,以及使用频率 freq。第二个 key_table 以键值 key 为索引,每个索引存放对应缓存在 freq_table 中链表里的内存地址,这样我们就能利用两个哈希表来使得两个操作的时间复杂度均为 O(1)。同时需要记录一个当前缓存最少使用的频率 minFreq,这是为了删除操作服务的。对于 g.原创 2021-05-16 11:54:19 · 316 阅读 · 0 评论 -
LRU算法的实现
分析LeetCode 146就是实现一个LRU算法,LRU算法的原理不再记录。LRU算法的实现的核心数据结构是哈希链表,就是双向链表和哈希表的结合体。LRU算法需要满足下面3个条件。1)cache中的元素必须是有时序的,以区分最近使用的和久未使用的数据,当容量满之后要删除最久未使用的那个元素腾出位置 ;2)我们要在cache中快速找某个key是否存在并得到value;3) 每次访问cache中的某个key,需要将这个元素变为最近使用的,也就是说cache要支持在任意位置快速插入和删除元素。哈希链表可以满.原创 2021-05-14 23:51:03 · 483 阅读 · 0 评论 -
LeetCode 215 数组中的第K个最大元素
分析维护一个小根堆,当堆的大小大于K的时候,就把堆顶元素pop。时间复杂度是O(N*logK),这个堆的作用就相当于一个筛子,把数组中前K大的数留下,堆顶元素即为第K大元素。代码class Solution {public: int findKthLargest(vector<int>& nums, int k) { priority_queue<int, vector<int>, greater<int>> que.原创 2021-05-14 16:19:27 · 76 阅读 · 0 评论 -
数组的前缀和及查分数组
1,前缀和主要适用场景是原始数组不会被修改的情况下,频繁查询某个区间的累加和。这里就不写前缀和的代码了,就是用一个数组记录下原有数组的前缀和。比如,prefix[i]就代表着nums[0…i-1]所有元素的累加和,如果我们想求区间nums[i…j]的累加和,只要计算prefix[j + 1] - prefix[i]即可,而不需要遍历整个区间求和。(需要注意的是使用场景是频繁查询某个区间的累加和,而不需要对原始数组进行频繁修改)2,查分数组的主要适用场景是**频繁对原始数组的某个区间的元素进行增减。**比原创 2021-05-13 23:55:38 · 716 阅读 · 0 评论 -
LeetCode 645 错误的集合
分析这个题可以使用哈希表记录一下,这样时间空间复杂度都是O(N),要想实现空间复杂度是O(1)的算法,需要使用映射。暂且将nuns中的元素变为[0…N -1],这样每个元素就和一个数组索引对应了,有一个元素重复了,同时导致一个元素缺失会导致有两个元素对应到了同一个索引,而且会有一个索引没有元素对应过去。我们可以通过将每个索引对应的元素变成负数,以表示这个索引被对应过一次了。缺失的元素索引最后对应的数据是正的,这样就可以找到重复和缺失的元素了。代码class Solution {public: .原创 2021-05-13 17:16:05 · 124 阅读 · 0 评论 -
LeetCode 面试题04.05 合法的二叉搜索树
分析要解决这道题首先我们要了解二叉搜索树有什么性质可以给我们利用,由题目给出的信息我们可以知道:如果该二叉树的左子树不为空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;它的左右子树也为二叉搜索树。这启示我们设计一个递归函数 helper(root, lower, upper) 来递归判断,函数表示考虑以 root 为根的子树,判断子树中所有节点的值是否都在 (l,r) 的范围内(注意是开区间)。如果 root 节点的值 val 不在 (l.原创 2021-05-13 11:20:41 · 90 阅读 · 0 评论 -
LeetCode 268 丢失的数字
分析位运算中异或运算,相同得0,不同得1,0与任何数A做异或运算的结果都是A,且异或运算满足交换律。这道题目可以假设先补齐一位,这样做以后可以发现除了缺少元素之外,所有的索引和元素都组成一队了,只要把所有的元素和索引做异或运算,成对儿的数字都会消失为0,最后剩下的元素即为丢失的元素。代码class Solution {public: int missingNumber(vector<int>& nums) { int ans = 0; ..原创 2021-05-12 22:01:25 · 69 阅读 · 0 评论 -
LeetCode 316 去除重复字母
分析这个题是去重相关算法中难度最大的,这道题搞懂,其他的就不在话下了。这道题目需要保证以下三点:1)要去重2)去重字符串中的字符顺序不能打乱s中字符出现的相对顺序3)在所有符合上面两条要求的所有字符串中,取字典序最小的作为最终结果先只考虑前两点,我们可以使用一个栈stk和一个数组inStack来辅助实现。栈中存放的是满足前两点的字符串。当是inStack[s[i]]在栈中就忽略这次处理,否则把s[i]入栈,更新inStack[s[i]]的值。然后考虑怎么来满足第三点,我们使用一个count数组.原创 2021-04-21 10:13:09 · 81 阅读 · 0 评论 -
二分查找总结
1,最普通的二分查找,数组中没有重复元素二分查找的概念已经很熟悉了,这里直接上代码,需要注意的点都在代码中以注释的形式标注。int binarySearch(int[] nums, int target){ int left = 0; int right = nums.size() - 1; while(left <= right){//这里有没有=号,取决于是左闭右开还是左闭右闭 //这里求mid之所以不写成mid = (right + left)/2,是有可能会整数溢出,而代码中这原创 2021-04-19 14:28:25 · 69 阅读 · 0 评论 -
LeetCode 376 摇摆序列
分析 这道题是是个贪心的题目,如果把数组中的点在二位坐标中画出来,是一个折线,只需要计算拐点的次数就可以了,需要注意的是代码利用了自动机的思想,比只写if else的代码可读性强如果在面试中写出这样的代码,能体现出扎实的基本功。代码class Solution {public: int wiggleMaxLength(vector<int>& nums) { int size = nums.size(); if...原创 2020-10-30 22:07:21 · 196 阅读 · 0 评论 -
LeetCode 295 数据流中的中位数
分析 维护两个堆,一个大根堆,一个小根堆。维护两个状态,大根堆的堆顶元素的值比小根堆的堆顶元素的值小,并且大根堆和小根堆个数差不大于1,这样中位数或是两个堆堆顶的平均值,或是其中一个堆的堆顶元素。这个和两个堆的元素的个数相关。插入元素的时候,维护两个堆状态的方法见代码。这个题是堆中典型的题目!!!!代码class MedianFinder {public: /** initialize your data structure here. */ priority_...原创 2020-10-19 22:04:54 · 96 阅读 · 0 评论 -
LeetCode 215 数组中第K个最大的元素
思路 在原来的数组上面建立一个长度为k的最小堆,堆于原来的数组从位置k开始依次向后遍历数组,当nums[i] > nums[0]的时候,执行swap(nums[i], nums[0]),然后向下调整,遍历完数组后,nums[0]就是数组中第K个最大的元素。时间复杂度: O(n*logk)空间复杂度: O(1)代码class Solution {public: //建立最小堆 void buildMinHeap(vector<int>&...原创 2020-10-12 21:12:37 · 81 阅读 · 0 评论