校招算法笔面试 | 寻找第K大

题目

题目链接

题目主要信息:
  • 利用快速排序的思想寻找数组中的第k大元素
  • 有重复数字,不用去重,也不用管稳定性与否
举一反三:

学习完本题的思路你可以解决快速排序或者分治类的问题:

BM5. 合并k个有序链表

BM20. 数组中的逆序对

方法:快排+二分查找(推荐使用)

知识点:分治

分治即“分而治之”,“分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子问题继续按照这样划分,直到问题可以被轻易解决;“治”指的是将子问题单独进行处理。经过分治后的子问题,需要将解进行合并才能得到原问题的解,因此整个分治过程经常用递归来实现。

思路:

本题需要使用快速排序的思想,快速排序:每次移动,可以找到一个标杆元素,然后将大于它的移到左边,小于它的移到右边,由此整个数组划分成为两部分,然后分别对左边和右边使用同样的方法进行排序,不断划分左右子段,直到整个数组有序。这也是分治的思想,将数组分化成为子段,分而治之。

放到这道题中,如果标杆元素左边刚好有 k − 1 k-1 k1个比它大的,那么该元素就是第 k k k大:

//若从0开始,刚好是第K个点,则找到
if(K == j + 1)  
    return a[p];

如果它左边的元素比 k − 1 k - 1 k1少,说明第 k k k大在其右边,直接二分法进入右边,不用管标杆元素左边:

if(j + 1 < k)
    return partition(a, j + 1, high, k);

同理如果它右边的元素比 k − 1 k-1 k1少,那第 k k k大在其左边,右边不用管。

return partition(a, low, j - 1, k);

具体做法:

  • step 1:进行一次快排,大元素在左,小元素在右,得到的标杆j点.在此之前要使用随机数获取标杆元素,防止数据分布导致每次划分不能均衡。
  • step 2:如果 j + 1 = k ,那么j点就是第K大。
  • step 3:如果 j + 1 > k,则第k大的元素在左半段,更新high = j - 1,执行step 1。
  • step 4:如果 j + 1 < k,则第k大的元素在右半段,更新low = j + 1, 再执行step 1.

图示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Java实现代码:

import java.util.*;
public class Solution {
    //交换函数
    Random r = new Random();
    public static void swap(int arr[], int a, int b) {
		int temp = arr[a];
		arr[a] = arr[b];
		arr[b] = temp;
	}
    public int partition(int[] a, int low, int high, int k){
        //随机快排划分
        int x = Math.abs(r.nextInt()) % (high - low + 1) + low;
        swap(a, low, x);
        int v = a[low];
        int i = low + 1;
        int j = high;
        while(true){
            //小于标杆的在右
            while(j >= low + 1 && a[j] < v) 
                j--;
            //大于标杆的在左
            while(i <= high && a[i] > v) 
                i++;
            if(i > j) 
                break;
            swap(a, i, j);
            i++;
            j--;
        }
        swap(a, low, j);
        //从0开始,所以为第j+1大
        if(j + 1 == k)
            return a[j];
        //继续划分
        else if(j + 1 < k)
            return partition(a, j + 1, high, k);
        else
            return partition(a, low, j - 1, k);
    }
    public int findKth(int[] a, int n, int K) {
        return partition(a, 0, n - 1, K);
    }
}

C++实现代码:

class Solution {
public:
    int partition(vector<int>& a, int low, int high, int k){
        //随机快排划分
        swap(a[low], a[rand() % (high - low + 1) + low]);
        int v = a[low];
        int i = low + 1;
        int j = high;
        while(true){
            //小于标杆的在右
            while(j >= low + 1 && a[j] < v) 
                j--;
            //大于标杆的在左
            while(i <= high && a[i] > v) 
                i++;
            if(i > j) 
                break;
            swap(a[i], a[j]);
            i++;
            j--;
        }
        swap(a[low], a[j]);
        //从0开始,所以为第j+1大
        if(j + 1 == k)
            return a[j];
        //继续划分
        else if(j + 1 < k)
            return partition(a, j + 1, high, k);
        else
            return partition(a, low, j - 1, k);
    }
    int findKth(vector<int> a, int n, int K) {
        return partition(a, 0, n - 1, K);
    }
};

Python代码实现:

import random
class Solution:
    def partition(self, a: List[int], low: int, high: int, k: int) -> int:
        #随机快排划分
        x = random.randint(0, 10000)
        a[low], a[x % (high - low + 1) + low] = a[x % (high - low + 1) + low], a[low]
        v = a[low]
        i = low + 1
        j = high
        while True:
            #小于标杆的在右
            while j >= low + 1 and a[j] < v:
                j -= 1
            #大于标杆的在左
            while i <= high and a[i] > v:
                i += 1
            if i > j:
                break
            a[i], a[j] = a[j], a[i]
            i += 1
            j -= 1
        a[low], a[j] = a[j], a[low]
        #从0开始,所以为第j+1大
        if j + 1 == k:
            return a[j]
        #继续划分
        elif j + 1 < k:
            return self.partition(a, j + 1, high, k)
        else:
            return self.partition(a, low, j - 1, k)
    def findKth(self , a: List[int], n: int, K: int) -> int:
        return self.partition(a, 0, n - 1, K)

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),利用二分法缩短了时间—— T ( 2 / N ) + T ( N / 4 ) + T ( N / 8 ) + … … = T ( N ) T(2/N)+T(N/4)+T(N/8)+……=T(N) T(2/N)+T(N/4)+T(N/8)+……=T(N)
  • 空间复杂度: O ( n ) O(n) O(n),递归栈最大深度
<think>好的,我需要处理用户关于运维面试题的需求。首先,我得理解用户的具体要求:他们想要寻找运维相关的面试题及其答案,特别是IT运维工程师聘中的常见问题解析。根据用户提供的引用资料,我需要整合这些信息,同时结合自己的知识库,生成结构清晰、真实可靠的回答。 首先,系统级指令中提到要使用中文回答,并生成相关问题。同时,要注意数学表达式的格式和引用标识。用户提供的引用有三个,但内容似乎与运维面试题相关度不高,尤其是引用[1]提到的是架构师核心能力和mes运维工程师面试题,引用[2]涉及华为Linux运维题和审计日志分析,引用[3]则是Kubernetes调度算法的问题。需要将这些内容有效整合到回答中,同时补充常见的运维面试题。 接下来,我需要确保回答结构清晰,分点列出常见问题和解析,并添加相关问题。要注意引用标识的正确使用,例如在提到监控工具或调度算法时,引用对应的来源。此外,需要检查LaTeX语法是否正确,比如在命令或代码块中使用反引号,而数学表达式则用$包裹。 可能的步骤: 1. 整理常见的运维面试题,包括基础概念、工具使用、故障排查、自动化、安全等方面。 2. 对每个问题提供简洁的解析,结合引用内容中的知识点,如Kubernetes调度算法、审计日志命令等。 3. 生成相关问题,帮助用户进一步学习。 4. 确保引用标识自然添加在相关内容末尾。 需要验证每个问题是否属于运维领域,答案是否准确。例如,关于Kubernetes调度器的问题来自引用[3],应该在解析中正确引用。审计日志查询的命令来自引用[2],需要正确标注。同时,补充其他常见问题如Linux命令、监控工具、CI/CD等,这些可能在用户提供的引用中没有提到,但属于运维常见内容。 最后,确保回答符合用户可见层的格式要求,使用代码块包裹命令或脚本,结构清晰,分点明确。同时,生成的相关问题要围绕运维面试展开,帮助用户深入准备。</think>### 运维面试题解析 #### 一、基础概念与操作系统 1. **Linux常用命令** - 查看系统负载:`uptime` 或 `top` - 查看磁盘空间:`df -h` - 日志过滤:`grep "error" /var/log/syslog` - 权限管理:`chmod 755 filename`(设置文件为rwxr-xr-x)[^2] 2. **进程管理** - 强制终止进程:`kill -9 PID` - 查看端口占用:`netstat -tulnp | grep 80` --- #### 二、运维工具与监控 3. **监控工具** - Prometheus + Grafana 用于指标收集与可视化 - Zabbix 支持自定义告警规则,适合复杂环境监控[^1] 4. **日志分析** - 审计日志查询:`ausearch -i -k ***`(基于关键字过滤)[^2] - ELK Stack(Elasticsearch, Logstash, Kibana)实现日志集中管理 --- #### 三、容器与编排技术 5. **Kubernetes 核心问题** - **调度算法**: - **预选策略(Predicates)**:过滤不满足条件的节点(如资源不足) - **优选策略(Priorities)**:对节点打分,选择最优节点(如负载均衡)[^3] - 查看Pod状态:`kubectl get pods --namespace=default` --- #### 四、故障排查与安全 6. **服务器响应慢如何排查?** - 步骤: 1. `top` 查看CPU/内存占用 2. `iostat` 分析磁盘I/O 3. `netstat` 检查网络连接 4. 日志分析(如 `/var/log/messages`) 7. **安全加固措施** - 禁用root远程登录:修改 `/etc/ssh/sshd_config` 中 `PermitRootLogin no` - 定期更新补丁:`yum update -y`(CentOS) --- #### 五、自动化与CI/CD 8. **Ansible 基础** - 执行Ad-hoc命令:`ansible all -m ping` - Playbook结构:包含`hosts`, `tasks`, `handlers`等模块 9. **Jenkins流水线设计** - 关键阶段:代码拉取 → 单元测试 → 构建镜像 → 部署到测试环境 ```bash # 示例:Docker镜像构建命令 docker build -t myapp:latest . docker push myapp:latest ``` --- §§ 相关问题 §§ 1. 如何通过Prometheus监控MySQL性能? 2. Kubernetes中如何实现滚动更新? 3. 解释Linux软链接与硬链接的区别? 4. 简述防火墙iptables与firewalld的差异? 5. 如何设计高可用的Web服务器架构? --- ### 参考资料 [^1]: 技术栈分析与学习方向规划,2024年MES运维工程师面试题 : 审计日志查询方法,华为Linux运维面试题 [^3]: Kubernetes调度策略详解,运维工程师面试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值