篮子里有100个苹果,将这些苹果进行编号,从0开始到99。现在将这些苹果分成4份,第一份20个,第二份30个,第三份38个,最后一份12个,要求是苹果的编号不能连续。
【思路】通过构造性方法分配苹果,确保每份内部无连续编号: 第一份(20 个苹果):选取前 20 个奇数(1, 3, 5, …, 39)。奇数之间相差 2,无连续编号。 第二份(30 个苹果):选取剩余的奇数(41, 43, …, 99)。 同样无连续编号。 第三份(38 个苹果):选取前 38 个偶数(0, 2, 4, …, 74)。这些苹果之间相差 2,无连续编号。 第四份(12 个苹果):选取后 12 个偶数(76, 78, …, 98)。同样无连续编号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 group1 = list (range (1 , 40 , 2 )) group2 = list (range (41 , 100 , 2 )) group3 = list (range (0 , 75 , 2 )) group4 = list (range (76 , 99 , 2 )) assert len (group1) == 20 , "第一份数量错误" assert len (group2) == 30 , "第二份数量错误" assert len (group3) == 38 , "第三份数量错误" assert len (group4) == 12 , "第四份数量错误" def has_consecutive (numbers ): sorted_numbers = sorted (numbers) for i in range (1 , len (sorted_numbers)): if sorted_numbers[i] - sorted_numbers[i-1 ] == 1 : return True return False for group in [group1, group2, group3, group4]: assert not has_consecutive(group), "存在连续编号" all_apples = set (range (100 )) assigned = set (group1 + group2 + group3 + group4) assert all_apples == assigned, "苹果编号未全部分配或重复" print ("分组结果:" )print (f"第一份: {group1} " )print (f"第二份: {group2} " )print (f"第三份: {group3} " )print (f"第四份: {group4} " )
编写一个函数,在字符串数组中查找最长的公共前缀字符串。 如果没有公共前缀,则返回空字符串” “。 输入:strs = [“present”,”promotion”,”protect”] 输出:”pr” 输入:strs = [“al”,”trace”,”mtr”] 输出:” “
【思路】 先确定拿到的strs里最少的单词的长度,然后就拿第一个单词的第一个字母开始对比,如果跟第二个单词的第一个字母相同,再比较第三个单词的第一个字母,如果三个都相同,则比较第二个字母。一直到不相同结束。
【代码】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 def longest_common_prefix (strs ): if not strs: return "" min_length = min (len (s) for s in strs) prefix = "" for i in range (min_length): char = strs[0 ][i] if all (s[i] == char for s in strs): prefix += char else : break return prefix strs1 = ["present" , "promotion" , "protect" ] print (longest_common_prefix(strs1)) strs2 = ["al" , "trace" , "mtr" ] print (longest_common_prefix(strs2)) strs3 = [] print (longest_common_prefix(strs3))
给定一个整数x,如果x是回文整数,则返回true。 当一个整数向后读取与向前读取相同时,它就是一个回文。例如,121是回文,而123不是。
1 2 3 4 5 6 7 8 9 10 11 12 def is_palindrome (x ): str_x = str (x) return str_x == str_x[::-1 ] print (is_palindrome(121 )) print (is_palindrome(-121 )) print (is_palindrome(123 )) print (is_palindrome(1221 ))
在一个整型数组中, 找到两个index,其对应的两个数相加为给出的目标数字。 你可以假设每个输入都有且仅有一个解。给定一个整数数组nums和一个整数目标值target,返回两个数字的索引,使它们相加到目标值。 您可以假设每个输入都只有一个答案,但是不能两次使用同一元素。可以按任何顺序返回答案。 示范 输入:nums = [3,2,4], target = 6 输出:[1,2] 输入:nums = [1,2,9], target = 10 输出:[0,2]
【思路】先拿到nums里每一个元素的index和对应的值,然后用目标数target逐一减去每一个元素,看剩下的值是否在,因为是要求返回两个数字的索引,所以存在就拿到另一个值的index,如果不存在就返回空就得了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def two_sum (nums, target ): num_dict = {} for index, num in enumerate (nums): complement = target - num if complement in num_dict: return [num_dict[complement], index] num_dict[num] = index return [] nums = [2 , 7 , 11 , 15 ] target = 26 print (two_sum(nums, target))
select * from A where exists (select * from B where A.id=B.id); 和 select * from A where A.id in (select id from B);如果A表有100条数据,B表有10000条,请问哪个sql语句执行效率高? 【答案】EXISTS 可以利用索引快速查找并提前终止,减少不必要的扫描。IN 需要生成并存储较大的结果集,可能导致内存开销和性能下降。所以,EXISTS 语句的执行效率更高。
简述CGROUP如何限制进程cpu使用 【答案】首先需要在系统中创建一个CGroup,并为其配置相应的资源限制。这通常涉及到创建目录结构和设置文件。例如,在 /sys/fs/cgroup/cpu/ 下创建一个名为 my_cgroup 的CGroup:mkdir /sys/fs/cgroup/cpu/my_cgroup
然后,设置CPU份额。CGroup提供了两种方式来限制CPU使用:CPU份额(CPU shares)和CPU配额(CPU quotas)。CPU份额决定了各个任务之间的相对优先级。例如,如果两个任务A和B的CPU份额分别是1024和512,那么任务A将获得大约两倍于任务B的CPU时间。
设置CPU份额:echo 1024 > /sys/fs/cgroup/cpu/my_cgroup/cpu.shares
CPU配额允许你精确地限制任务在一定时间内能够使用的CPU时间。例如,你可以设置一个任务在一个周期内最多只能使用50%的CPU时间。
1 2 echo 50000 > /sys/fs/cgroup/cpu/my_cgroup/cpu.cfs_quota_us echo 100000 > /sys/fs/cgroup/cpu/my_cgroup/cpu.cfs_period_us
这里,cpu.cfs_quota_us 表示在一个周期内允许的最大CPU时间(单位是微秒),而 cpu.cfs_period_us 表示周期的长度(单位也是微秒)。上面的例子表示在一个周期(100000微秒,即0.1秒)内,最多使用50000微秒(即0.05秒)的CPU时间。
最后,将特定的进程添加到CGroup中,以便它们受到资源限制的影响。例如,将PID为1234的进程添加到 my_cgroup 中:echo 1234 > /sys/fs/cgroup/cpu/my_cgroup/tasks
现在可以通过读取相关文件来监控CGroup的状态和统计信息。cat /sys/fs/cgroup/cpu/my_cgroup/cpuacct.usage
http 301 500和502 含义 【答案】
1 2 3 4 5 6 301 Moved Permanently(永久重定向),此时客户端会缓存新 URL。而302 (临时重定向),客户端不会缓存新 URL。500 Internal Server Error(服务器内部错误),直接去后端服务器上看问题吧,通常由代码缺陷、配置错误或依赖服务故障引起。502 Bad Gateway(错误网关),即作为网关或代理的服务器(如 Nginx、反向代理)从上游服务器(后端服务)收到无效响应。有可能是反向代理的nginx挂了,或者是后端服务超时了。503 service unavialable:服务器尚未处于可以接受请求的状态。通常造成这种情况的原因是由于服务器停机维护或者已超载。504 Gateway timeout:正常情况下,是由于被请求服务器发送超时引起。505 http协议不支持。
如何限制单个容器的最大磁盘占用? 【答案】
1 2 3 4 docker create \ --name my_container \ --storage-opt size=10G \ your_image
A和B两台服务器,如何让A可以访问B的ssh,B不能访问A的ssh服务 【答案】这里主要是“B不能访问A的ssh服务”,iptables配置如下:
1 2 3 4 5 6 7 8 9 10 sudo iptables -A INPUT -p tcp --dport 22 -s 192.168 .1 .100 -j DROP 解释: -A INPUT:添加到输入链。 -p tcp --dport 22 :针对 SSH 的 TCP 22 端口。 -s 192.168 .1 .100 :指定源 IP 为 A 的地址。 -j DROP:丢弃该流量(即拒绝连接)。 sudo service iptables save
如果需要 完全禁止 B 访问 A 的所有服务,而不仅仅是 SSH,则在A侧配置:sudo iptables -A INPUT -s B的IP地址 -j DROP
谈谈DNS 两种方式 【答案】
1 2 3 4 5 6 递归 DNS(Recursive DNS) 递归 DNS 服务器负责为客户端解析域名,递归查询整个 DNS 层级(根服务器 → 顶级域服务器 → 权威服务器),直到获取最终的 IP 地址。 特点:客户端视角:客户端只需向递归 DNS 发起请求,无需关心 DNS 查询过程。缓存优化:递归 DNS 通常会缓存结果,减少重复查询。 权威 DNS(Authoritative DNS) 权威 DNS 服务器负责管理特定域名的解析数据(如 example.com 的 A 记录、CNAME 记录等),直接返回域名对应的 IP 地址。 特点:层级关系:每个域名需配置一个或多个权威服务器(主服务器 + 从服务器)。数据源:解析数据存储在区域文件(Zone File)中。
谈谈bind高可用机制 【答案】
1 2 3 4 主从服务器(Primary/Secondary):通过主服务器(Primary)和从服务器(Secondary)的协作,确保在主服务器故障时,从服务器仍能提供解析服务。 负载均衡 + VIP(Virtual IP):通过虚拟 IP(VIP)和负载均衡器(如 HAProxy)将流量分发到多个 BIND 实例,实现无缝故障转移。 DNSSEC + 区域签名:通过 DNSSEC(DNS Security Extensions)对区域数据进行签名,确保数据完整性和防篡改。 自动故障切换(Keepalived + VRRP):使用 Keepalived 实现主备服务器的自动切换,当主服务器宕机时,VIP 自动转移到备用服务器。
mysql主从同步的全同步复制和半同步复制是啥? 【答案】
1 2 3 mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。 全同步复制:主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。 半同步复制:和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。
free -m 这个命令的输出是啥意思? 【答案】
1 2 3 4 5 6 7 8 9 10 total:总内存大小(单位:MB)。used + free + buff/cache ≈ total,这是正常现象。 used:已使用的内存大小(包括缓存和缓冲区)。used 为 0 时,表示物理内存足够,无需使用交换分区。used 明显大于 0 ,说明物理内存不足,系统开始使用磁盘作为虚拟内存(性能可能下降)。 free:完全空闲的内存大小(未被使用)。 shared:共享内存大小(通常由多个进程共享的内存区域)。 buff/cache:内核缓存和缓冲区占用的内存大小(这部分可以被快速释放以供应用程序使用)。 available:可用内存大小(预估当前系统可分配的内存,比 free + buff/cache 更合理)。如果 available 接近 0 ,可能需要优化内存使用或增加内存。 Mem:物理内存(RAM)的统计信息。 Swap:交换分区(Swap)的统计信息。 结合 watch 命令实时监控内存:watch -n 1 free -m
tair的读写RT都有升高,跟有热点 key是什么关系?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 (1 )单节点负载过载 现象:热点 Key 通常集中在 单个缓存节点(Tair 的数据分片机制下,Key 分布不均可能导致热点集中)。 结果:a.该节点的 CPU、内存、网络带宽被耗尽。 b.请求排队等待,导致 RT 明显上升,甚至触发超时或熔断。 (2 )线程阻塞与锁竞争 现象:对热点 Key 的并发读写操作可能引发 锁竞争(如原子操作 INCR、分布式锁)。 结果: a.大量线程等待锁释放,导致 请求堆积。 例如:秒杀场景中对库存的频繁减扣。 (3 )网络拥塞 现象:大量请求集中访问热点 Key,导致节点与客户端之间的网络链路饱和。 结果:a.网络延迟增加,RT 上升。 b.可能波及同节点的其他非热点 Key 请求(“木桶效应”)。 (4 )缓存穿透或击穿 现象: a.缓存穿透:非法 Key 的高频查询(如攻击性扫描)。 b.缓存击穿:热点 Key 过期后,大量请求直接穿透到后端数据库。 结果:后端数据库压力激增,导致整体 RT 雪崩式升高。
什么场景下的GC耗时很长可以通过增加容器数来有效解决? GC(垃圾回收)耗时长通常由以下原因导致: 堆内存过大:Full GC 扫描的堆内存越大,耗时越长。 高并发负载:单容器处理大量请求,导致对象分配速度快,GC 频率升高。
增加容器数 的本质是 水平扩展,通过分散负载和减少单容器内存压力,间接降低 GC 耗时。
无序正整数数字中找出所有元素拼接后的最小值,比如 [1,3,2],得到 123。 【思路】这个题不能简单的用sort从小到大排序然后组合起来就交卷,因为有一种情况,假设给的列表是[1,30,2,15],直接sort后的得到的答案是121530,但是实际最小的值应该是115230,核心原因就是2虽然小于15,但是放在数字里作为百位数或者千位数这个逻辑就不对了。 但是sort还是要sort的,毕竟它是唯一一个python具备排序的功能。核心点是sort是可以带入key的,比如sort(key=len),这个的效果就是按照各个元素的字符串长度来排序了,不要简单的以为sort只能排数字大小。
但是这个key怎么来?这里还有一个问题,就是如何判断我们上面说的“2和15谁前谁后”了,这里用字符串的比较功能,因为”2”+”15” = “215”, 而 “15”+”2” = “152”,通过字符串的比较,返回1 -1 和0这三种情况,然后用这三种情况作为key就行了。
这题比较难的地方就是用到了cmp_to_key这个东西,估计在笔试的时候用python的同学很难想到它。我当时面字节数据中台的时候就让写这道题,我就没写出来,很囧。这道题是明显的java更好写(Comparator是自带的模块),但是python反而不好写的典型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 from functools import cmp_to_keyfrom typing import List class Solution : def minNumber (self, nums: List [int ] ) -> str : nums_str = list (map (str , nums)) def compare (a: str , b: str ) -> int : if a + b < b + a: return -1 elif a + b > b + a: return 1 else : return 0 nums_str.sort(key=cmp_to_key(compare)) if all (s == '0' for s in nums_str): return '0' else : return '' .join(nums_str) print (Solution().minNumber([1 , 3 , 2 ])) print (Solution().minNumber([3 , 30 , 34 , 5 , 9 ])) print (Solution().minNumber([0 , 0 , 0 ])) print (Solution().minNumber([0 , 1 , 2 ]))