MySQL基础知识
MySQL基础知识校招面经整理、热身
//
1. 聚簇索引和普通索引:聚簇索引指其 B+ 树的叶子节点包含了指向数据的指针。查询聚簇索引时,只需顺着该指针即可访问到数据。普通索引指叶子节点处的索引项只是存储了某个聚簇索引的索引值,而非直接指向数据。查询普通索引时,还需额外回表 1 次,通过查到的索引值查找该聚簇索引,最终获得数据。MySQL中 InnoDB 主键索引一定为聚簇索引,不设主键的话第一个唯一索引字段即为聚簇索引,没有唯一索引字段的话,使用隐藏字段自增主键作为聚簇索引。由于聚簇索引在一张表中最多创建一个,所以其余索引为普通索引。
2. 普通索引和聚簇索引是单独存在表还是另外开一个表:不太确定这题要问什么。尝试从叶子结点的结构来回答。
聚簇索引的叶子结点是指向了该结点值所在的数据行的,也就是说指向了原数据表。
普通索引的叶子节点则是指向了一个新表,表中存储了当前索引值对应的所有主键值。从这个角度来说,普通索引确实创建了一个新表,而聚簇索引没有(直接在原数据表的基础上以主键构建索引)
3. HashMap 和 B 树有何异同,为什么数据库一般使用b树来当索引:相同:好像没 ...
数据结构基础知识
数据结构基础知识校招面经整理、热身
//
1. 红黑树、B+ 树、B 树、二叉搜索树:
二叉搜索树:又称 BST,是为了实现在 O(logn) 时间内完成对有序集合中的元素完成一次查找,而设计的数据结构。
B树:二叉搜索树在最坏情况下,如果元素按顺序插入,会失去平衡退化为链表,查找的效率为 O(n),为了解决这个平衡问题,引入 AVL 树、 B 树。B树中的元素会优先填满每层的结点,达到最大值以后分裂,分裂时会调整父节点和其他子节点,实现平衡。同时 B 树的一层可以设定允许容纳多个节点,进一步降低树高。
红黑树: B 树的一个缺点在于其插入、删除节点时的分裂逻辑较为复杂,对大量写操作不友好。为了解决这个问题,引入红黑树。红黑树是某棵确定的 2-3 B树的另一种表现形式(或者说,给定一种旋转规则(LL、LR、RR旋转),则一棵红黑树唯一地映射着一棵 2-3 B 树,反之亦然)。其某个红结点与其父节点(一定为黑色)可以视为对应的 2-3 B 树的某一个结点的2个元素。至此,我们将 B 树的结点分裂规则,转化为了红黑树的旋转规则,大大简化了判断逻辑。
B+ 树: B 树的另一缺点在于,对 ...
41. 缺失的第一个正数
自定义哈希算法充分利用原数组空间
//
题目链接-来源:力扣(LeetCode)
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0]输出:3
思路:假设不限制空间复杂度,本题显然可以用普通的哈希表存储所有元素,然后从 1 开始遍历正整数,直到找到第一个不发生冲突的正整数即为答案。现在要求 O(1) 空间复杂度,我们考虑如何充分利用原数组空间,螺蛳壳里做道场。我们总共有 n 个元素,并且有长度为 n 的数组空间,并且 n 个元素当中,会有 /[0,n] 个元素或者小于等于 0、或者大于 n(n 个不相同的正整数若均小于等于 n,则最小未出现的元素为 n + 1, 否则,答案一定在 (0,n]之间),不在我们考虑之列,也就是说,我们的数组空间是完全够用的,经过充分的交换之后,可以把所有处于 (0,n] 之间的元素哈希到合适的位置上。(理论上,这里有无数种哈希算法,比如 Hash(x) = (x + a) % n, ...
40. 组合总和 II
回溯遍历可能选项,二分法加快效率,39题的变式
//
题目链接-来源:力扣(LeetCode)
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
注意:解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,输出:[[1,1,6],[1,2,5],[1,7],[2,6]]
思路:此题完全可以沿用上一题的模板。我们先对数组排序,之后二分地找到最大的小于等于 target 的数,从这个数开始向下回溯递归地进行 DFS搜索。只需注意,上题的每个元素是无限量的,而本题中的元素有限。为了不漏掉重复的元素,同时不重复考虑重复的元素,我们只需在每次递归当中,在循环每次要进入下层递归前,判断当前循环考虑的元素是否与前一次循环重复,重复则略过即可。时间复杂度:O(2^n * n) 其中 2^n 是指元素个数为 n 的集合所对应的幂集中的元素数量。空间复杂 ...
39. 组合总和
回溯遍历可能选项,二分法加快效率
//
题目链接-来源:力扣(LeetCode)
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。解集不能包含重复的组合。 示例 1:
输入:candidates = [2,3,6,7], target = 7,所求解集为:[ [7], [2,2,3]]
思路:首先,大于 target 的元素不可能进入解集。因此可以用二分法先确定 target 的大致位置。我们寻找满足小于等于 target 的最大元素的下标,在此下标范围内的元素全部进入我们的备选集。之后在备选集中按一定的顺序(从小到大或从大到小)选择选项,选择某个选项 val 后,用 target 值减去 val,获得的新值 deeperTarget 若不等于 0,我们就把 deeperTarget 作为新的 target 递归地放到剩余的备选集当中查找(记住,深层递 ...
38. 外观数列
迭代计数前驱字符串的特征
//
题目链接-来源:力扣(LeetCode)
给定一个正整数 n ,输出外观数列的第 n 项。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
你可以将其视作是由递归公式定义的数字字符串序列:
countAndSay(1) = “1”countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。前五项如下:
1
11
21
1211
111221
第一项是数字 1描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 “11”描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 “21”描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 “1211”描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 “111221”要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述 ...
37. 解数独
用二进制位记录冲突信息,用位运算替代效率较低的哈希运算。
//
题目链接-来源:力扣(LeetCode)
编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
示例:
输入:board = [[“5”,”3”,”.”,”.”,”7”,”.”,”.”,”.”,”.”],[“6”,”.”,”.”,”1”,”9”,”5”,”.”,”.”,”.”],[“.”,”9”,”8”,”.”,”.”,”.”,”.”,”6”,”.”],[“8”,”.”,”.”,”.”,”6”,”.”,”.”,”.”,”3”],[“4”,”.”,”.”,”8”,”.”,”3”,”.”,”.”,”1”],[“7”,”.”,”.”,”.”,”2”,”.”,”.”,”.”,”6”],[“.”,”6”,”.”,”.”,”.”,”.”,”2”,”8”,”.”],[“.”,”.”,”.”,”4”,” ...
36. 有效的数独
用哈希表验证数独表是否有效。
//
题目链接-来源:力扣(LeetCode)
请你判断一个 9x9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
注意:
一个有效的数独(部分已被填充)不一定是可解的。只需要根据以上规则,验证已经填入的数字是否有效即可。
示例 1:
输入:board =[[“5”,”3”,”.”,”.”,”7”,”.”,”.”,”.”,”.”],[“6”,”.”,”.”,”1”,”9”,”5”,”.”,”.”,”.”],[“.”,”9”,”8”,”.”,”.”,”.”,”.”,”6”,”.”],[“8”,”.”,”.”,”.”,”6”,”.”,”.”,”.”,”3”],[“4”,”.”,”.”,”8”,”.”,”3”,”.”,”.”,”1”],[“7”,”.”,”.”,”.”,”2”,”.”,”.”,”.”,”6”],[“.” ...
35. 搜索插入位置
二分法查找有序数组
//
题目链接-来源:力扣(LeetCode)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5输出: 2
思路:借鉴上一题的思路。我们要找到 target,其实就是要找到 target - 1 右侧的最大值所处的位置。若存在 target,则返回目标索引,否则,该索引也是我们所需的插入位置。时间复杂度:O(n)空间复杂度:O(1)
实现:12345678910111213141516171819class Solution { public int searchInsert(int[] nums, int target) { int index = helper(nums, target - 1); return index; } private int helper(int[] arr, int target) { ...
34. 在排序数组中查找元素的第一个和最后一个位置
二分法查找有序数组
//
题目链接-来源:力扣(LeetCode)
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8输出:[3,4]
思路:已知有序数组,那么大体框架依然是二分法。问题在于,我们二分查找的目标是什么。举例,对于示例中的 nums = [5,7,7,8,8,10], target = 8,我们需要二分地查找第一个 ‘8’(位于下标 3 处)和最后一个 ‘8’(位于下标 4 处)。这样的话,我们需要实现两套逻辑,两套逻辑都要先二分找到 target(或者确定 target 不存在),然后第一个逻辑定位到最左侧的 target 值,第二个定位到最右侧。当然,我们也可以进行适当处理,用同一套逻辑覆盖这个问题。比如,我们的查找目标是实现 「二分查 ...
