b站外包面试题
旋转数组
package main
import (
"fmt"
)
// rotate 函数将数组中的元素向右旋转 k 个位置
func rotate(nums []int, k int) {
n := len(nums)
k %= n // 如果 k 大于数组长度,则取 k 对数组长度的模
// 定义一个局部函数,用于翻转数组中的指定范围元素
reverse := func(nums []int, start, end int) {
for start < end {
nums[start], nums[end] = nums[end], nums[start]
start++
end--
}
}
// 步骤1:翻转整个数组
reverse(nums, 0, n-1)
// 步骤2:翻转前 k 个元素
reverse(nums, 0, k-1)
// 步骤3:翻转剩余元素
reverse(nums, k, n-1)
}
func main() {
// 测试案例
testCases := []struct {
nums []int
k int
result []int
}{
{[]int{1, 2, 3, 4, 5, 6, 7}, 3, []int{5, 6, 7, 1, 2, 3, 4}},
{[]int{-1, -100, 3, 99}, 2, []int{3, 99, -1, -100}},
{[]int{1, 2}, 3, []int{2, 1}}, // k 大于数组长度的情况
}
for i, tc := range testCases {
fmt.Printf("Test Case %d:n", i+1)
fmt.Println("Input:", tc.nums, "k:", tc.k)
rotate(tc.nums, tc.k)
fmt.Println("Output:", tc.nums)
fmt.Println("Expected:", tc.result)
fmt.Println()
}
}
mysql索引相关
索引常见题目
-
什么是索引?
索引充当的是数据的目录。 -
什么是存储引擎?
它是如何存储数据,如何为存储的数据建立索引、更新、查询的实现方法。
mysql常用存储引擎 MyISAM、InnoDB、Memory, InnoDB在mysql5.5之后的默认引擎。
InnoDB 支持行锁 -
索引有哪几类?
- 数据结构分
- B+Tree索引、Hash索引、Full-Text索引
- 物理存储分
- 聚簇和非聚簇
-
聚簇和非聚簇索引有什么区别?
- 聚簇索引就是主键索引建立在主键字段上的索引
drop table if exists student; create table student( student_id int primary key, student_name varchar(16), class_id int not null, index(class_id) ) engin= InnoDB; -- 添加一条数据 insert into student(student_id,student_name,class_id) values(1,'小智',99) -- 这里的student_id有个(聚簇索引)主键索引和class_id一个非聚簇索引(二级索引)
- 非聚簇索引存的并不是真正的数据,而是聚簇索引的主键ID,所以当我们用非聚簇索引的时候会,会去主键索引里面找这个值,这个操作叫做回表。
- 由此可见 聚簇索引比非聚簇索引的查询效率更高。
- 因为每个表的主键索引(聚簇索引)只能有一个,但是非聚簇索引的ID就没有限制了。
-
什么时候需要索引?/不需要索引?
索引可以优化查询效率但是也有缺点- 需要占磁盘空间,数量越多占磁盘空间越多。
- 创建和维护索引耗时,数据量越大耗时越大。
- 降低表的增删改的效率,每次增删改,b+tree是有序的,需要动态维护。
- 什么时候用索引?
- 字段具有唯一性,如身份证。
- 经常需要用到where查询的字段。
- 经常用group by 和 order by 这样就不用排序了,b+tree已经排序好了
- 什么时候不需要索引?
- where 和 group by 里面不需要就不要创建索引。
- 有大量重复字段,比如男女,mysql有优化器,每次都查询一半非常耗时。
- 表数据量很小。
- 经常更新的字段不要创建索引,比如用户余额。B+tree会重复动态的更新,影响性能。
-
如何优化索引?有哪些手段?
- 前缀索引优化;
注意事项: order by 无法使用。
前缀索引不能作为覆盖索引使用。
一般是对文本的前几个字符创建索引,比如某个商品前十个字符。
一般对BLOB和TEXT列进行索引,或者很长字符varchar()字段。
当某个字段数量较大,且查询频繁,使用前缀索引优化可以减小索引文件的打小,让每个索引页保存更多值,从而提高查询效率。
-- 创建user表 CREATE TABLE `tb_user` ( user_id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_name varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; -- 创建前缀索引 长度为5的索引 alter table tb_test add key(user_name(5)) -- 如何计算到底创建什么长度的索引? -- 1.计算use_rname字段的全列区分度。 select count(distinct user_name) / count(*) from tb_user; -- 2.计算前缀长度。 select count(distinct left(user_name,prefix_length)) / count(*) from tb_user; -- 3.最后就是调整这个值 这个值和前面1的值差不多就可以了。
- 覆盖索引优化;
指的是扫描索引,不需要回表的操作。
注意事项:用于innodb 因为是b+tree 索引是有序的,并且子节点存的是索引,叶子节点存的是数据
create table `tb_user`( user_id bigint(50) not null, data1 varchar(20) no null, data2 tinyint(2) not null, ... parimary key(user_id), key indx_tb_01(data1,...), key... ) engine=innodb defalult charset=utf8 -- Extra 是 NULL --加覆盖索引 create index idx_tb_02(data1,data2) on tb_user;
- 主键索引优化自增主键;
为什么自增就能优化?- 因为b+tree插入的记录是有序的,追加操作,不需要移动数据。多余动作会增加耗时。
- 使用非自增的话会导致页分裂,页分裂会造成大量的内存碎片,导致索引结构不紧凑,影响查询的效率。
也可以用雪花算法自行设计主键。
create table `tb_user`( user_id int(4) primary key auto_increment, user_name varchar(20) not null );
- 防止索引失效;
几个索引失效场景
like %key
对索引使用函数
对索引进行表达式计算
对索引进行隐式类型转换
联合索引非最左匹配原则 - 索引设置为NOT NULL
为什么索引设置为NOT NULL?- count计算会省略NULL,计算麻烦,优化器在做索引的时候更复杂,难以优化。
- Null没有意义,还会占据物理空间。
- 前缀索引优化;
-
建立联合索引和联合索引使用
https://cloud.tencent.com/developer/article/2003084 腾讯大佬示例索引为什么要用id不用字符
为什么不用B树
b树和b+tree的区别:
-
b树的子节点存储的是主键索引。
-
b树的I/O磁盘次数比b+tree多。
-
b+tree的叶子节点存储数据是有序的,方便范围查询。
-
b+tree子节点
-
Linux相关命令和场景
https://blog.csdn.net/wzk4869/article/details/132855372 -
docker和k8s
https://cloud.tencent.com/developer/article/2009072