2025高频面试算法总结篇【排序】

文章目录

  • 直接刷题链接直达
  • 把数组排成最小的数
  • 删除有序数组中的重复项
  • 求两个排序数组的中位数
  • 求一个循环递增数组的最小值
  • 数组中的逆序对
  • 如何找到一个无序数组的中位数
  • 链表排序
  • 从一大段文本中找出TOP K 的高频词汇


直接刷题链接直达

  • 把一个数组排成最大的数
    • 剑指 Offer 45. 把数组排成最小的数
    • 面试官说需要 通过 补位 思想(普通的compare再sort并不满意,但补位思想似乎不适用于有重复元素的情况)
  • 如何给一个很大的无序数组去重
    • 26. 删除排序数组中的重复项(给排序数组去重)
  • 求两个排序数组的中位数
    • 要求时间复杂度 O(log(m+n))
    • 二分查找,递归求整个数组中第K大的元素,完整代码需要仔细考虑多种边界条件
    • 4.寻找两个有序数组的中位数
  • 求一个循环递增数组的最小值
    • 153. 寻找旋转排序数组中的最小值 (无重复元素,二分,总有一半有序,注意边界)
    • 154. 寻找旋转排序数组中的最小值 II (有重复元素,需要解除相等时的死循环)
  • 数组中的逆序对
    • 归并排序 && 递归的应用
    • 引入辅助数组临时存放排序好的数据
    • 归并时指向两个指针末尾,逐次向前并统计
    • 面试题51. 数组中的逆序对
  • 如何找到一个无序数组的中位数
    • 295. 数据流的中位数 (建立两个堆,最大堆&最小堆,复杂度分析)
    • 找出一个无序数组的中位数 (快排,缩小Partition区域 / 取一半元素建堆)
  • 链表排序
    • 需要 nlog(n) 时间复杂度和常数级空间复杂度
    • 归并排序的应用(Bottom Up)
    • 找到中点,断开链表(通过快慢两个指针)
    • 交替双指针合并
    • 148. 排序链表
  • 手写主流排序算法 & 各种算法的复杂度/稳定性分析
    • 常见问题
      • 手写快排 / 堆排
      • 快排的复杂度分析(最好/最坏/平均)
      • 堆排中建堆的时间复杂度分析 --> O(n)
        • 堆排序中建堆过程时间复杂度O(n)怎么来的?
        • 为什么建堆的时间复杂度是O(n)?
      • 归并排序的 Top-Down & Bottom-up 策略
      • 不同排序的稳定性分析
      • 冒泡排序的优化策略(华为)
        • 设置flag位,一轮未交换数据即已完成排序,提前结束
        • 记住本轮最后一次交换发生的位置lastExchange,下次内层循环到此终止即可
    • 排序算法稳定性
    • 排序算法可视化
    • 快排 Wiki / 堆排 Wiki / 归并排序 Wiki
    • 堆排序(Heapsort) (特别好的讲解)
    • 冒泡排序算法及其两种优化
  • (Top K 问题)给定一个无符号,包含10亿个数的数组,如何取出前100大的数
    • 答题思路
      • 首先询问资源 --> 内存 / 核数 / 单机or多机,如可用多机 --> MapReduce思想
      • 堆排 O(nlogk),可以单机处理海量数据(在内存受限情况下),如果k较小,趋近于 O(n)
        • 建立一个容量为k的大/小顶堆
        • n个元素逐一比较,O(logk) 完成删除和插入操作
      • 全局排序, O(nlogn) (数据量较小时才可行)
      • 冒泡(k个),O(kn)
      • 快排划分 O(n), 每次递归处理一侧的数据,理论上可以理解为每次折半,缺点 --> 存在内存不够的问题,因为需要一次读入所有数据
    • 算法必学:经典的 Top K 问题(基本思路篇)
    • 海量数据处理 - 10亿个数中找出最大的10000个数(top K问题) (各种资源场景分析,面试前可参考)
    • 最小的K个数(代码实现,首选堆排)
  • Java自带的 sort() 方法是如何实现的
    • Array.sort() / Collections.sort()
    • DualPivotQuicksort(双轴快速排序)
    • Arrays.sort和Collections.sort实现原理解析
    • Collections.sort()和Arrays.sort()排序算法选择
  • 写一个快速划分数据集的算法,要求测试集用新数据,训练集用老数据
    • 数据格式为 Record(id, timestamp)
    • 函数签名为 division(ArrayList dataset, double ratio), ratio为(0,1)的划分比例
    • 要求复杂度为O(n)
  • 从一大段文本中找出TOP K 的高频词汇
    • System Design Interview - Top K Problem (Heavy Hitters) (系统设计角度思考本题,如何权衡性能和效率,较为高阶)
    • 347. 前K 个高频元素 (数字频次代码实现,建堆,时间复杂度为nlog(k))
    • 692. 前K个高频单词 (词汇频次代码实现,思路一致)

把数组排成最小的数

题目:闯关游戏需要破解一组密码,闯关组给出的有关密码的线索是:

  • 一个拥有密码所有元素的非负整数数组 password
  • 密码是 password 中所有元素拼接后得到的最小的一个数
class Solution {public String crackPassword(int[] password) {String[] strs = new String[password.length];for (int i=0; i < password.length; i++) {strs[i] = password[i] + "";}Arrays.sort(strs, (a, b) -> (a + b).compareTo(b + a));StringBuilder sb = new StringBuilder();for (int i=0; i < password.length; i++) {sb.append(strs[i]);}return sb.isEmpty() ? "0":sb.toString();}
}

删除有序数组中的重复项

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。
class Solution {public int removeDuplicates(int[] nums) {if (nums.length == 0) return 0;int k = 0;for (int i = 1; i < nums.length; i++) {if (nums[i] != nums[k]) {nums[++k] = nums[i];}}return k+1;}
}

求两个排序数组的中位数

题目:
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

  • 算法的时间复杂度应该为 O(log (m+n)) 。

解法:
这道题的关键是 二分查找+数组切割,核心思路是 在较短数组上二分查找,然后通过数学推导找到合适的中位数。

  • 设定两个数组 nums1nums2,保证 nums1 总是最短的数组(这样可以减少二分查找的搜索范围)。

  • 对短数组进行二分查找,设 nums1 的长度为 mnums2 的长度为 n,则我们希望找到一个分割点 i(在 nums1 中),同时 j = (m + n + 1) / 2 - i(在 nums2 中)。

  • 确保分割点左侧的所有元素 ≤ 右侧的所有元素

  • nums1[i-1] <= nums2[j]

  • nums2[j-1] <= nums1[i]

  • 确定中位数

  • 如果 m + n奇数,中位数是左半部分的最大值 max(nums1[i-1], nums2[j-1])

  • 如果 m + n偶数,中位数是 (max(nums1[i-1], nums2[j-1]) + min(nums1[i], nums2[j])) / 2

public double findMedianSortedArrays(int[] nums1, int[] nums2) {// 保证 nums1 是较短的数组if (nums1.length > nums2.length) {return findMedianSortedArrays(nums2, nums1);}int m = nums1.length, n = nums2.length;int left = 0, right = m;int medianPos = (m + n + 1) / 2; // 中位数的位置while (left <= right) {int i = left + (right - left) / 2;  // nums1的分割点int j = medianPos - i;             // nums2的分割点int nums1LeftMax = (i == 0) ? Integer.MIN_VALUE : nums1[i - 1];int nums1RightMin = (i == m) ? Integer.MAX_VALUE : nums1[i];int nums2LeftMax = (j == 0) ? Integer.MIN_VALUE : nums2[j - 1];int nums2RightMin = (j == n) ? Integer.MAX_VALUE : nums2[j];if (nums1LeftMax <= nums2RightMin && nums2LeftMax <= nums1RightMin) {// 找到合适的分割点if ((m + n) % 2 == 0) {return (Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin)) / 2.0;} else {return Math.max(nums1LeftMax, nums2LeftMax);}} else if (nums1LeftMax > nums2RightMin) {// 需要向左移动right = i - 1;} else {// 需要向右移动left = i + 1;}}throw new IllegalArgumentException("输入的数组不符合条件");
}

求一个循环递增数组的最小值

题目: 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
class Solution {public int findMin(int[] nums) {if (nums == null || nums.length == 0) {throw new IllegalArgumentException("数组不能为空");}int left = 0, right = nums.length - 1;while (left < right) { // 这里是 left < right,而不是 left <= rightint mid = left + (right - left) / 2;if (nums[mid] > nums[right]) {  // 最小值一定在 mid 右侧left = mid + 1;} else {// 最小值可能在 mid 或左侧right = mid;}}return nums[left]; // 最终 left == right,返回最小值}
}

题目 : 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
  • 若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]
class Solution {public int findMin(int[] nums) {if (nums == null || nums.length == 0) {return 0;}int left = 0, right = nums.length - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] > nums[right]) {left = mid + 1;}else if (nums[mid] < nums[right]) {right = mid;}else {// nums[mid] == nums[right]right--;}}return nums[left];}
}

数组中的逆序对

题目 :在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个「交易逆序对」。请设计一个程序,输入一段时间内的股票交易记录 record,返回其中存在的「交易逆序对」总数。

class Solution {public int reversePairs(int[] record) {if (record == null || record.length < 2) return 0;mergeSort(record, 0, record.length - 1);return count;}public void mergeSort(int[] record, int left, int right) {if (left >= right) return;int mid = left + (right-left)/2;mergeSort(record, left, mid);mergeSort(record, mid+1, right);// 合并merge(record, left, mid, right);}int count = 0;public void merge(int[] record, int left, int mid, int right) {int[] temp = new int[right - left +1];int i = left, j = mid+1;int k = 0;while (i <= mid && j <= right) {if (record[i] <= record[j]) {temp[k++] = record[i++];}else {//当左边数组的大与右边数组的元素时,就对当前元素以及后面的元素的个数进行统计,//此时这个数就是,逆序数//定义一个计数器,记下每次合并中存在的逆序数。count += mid - i + 1;temp[k++] = record[j++];}}while (i <= mid) temp[k++] = record[i++];while (j <= right) temp[k++] = record[j++];//将新数组中的元素,覆盖nums旧数组中的元素。//此时数组的元素已经是有序的for(int t =0; t< temp.length;t++){record[left+t] = temp[t];}}
}

如何找到一个无序数组的中位数

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

例如 arr = [2,3,4] 的中位数是 3 。
例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。
实现 MedianFinder 类:

MedianFinder() 初始化 MedianFinder 对象。

void addNum(int num) 将数据流中的整数 num 添加到数据结构中。

double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

class MedianFinder {PriorityQueue<Integer> left;PriorityQueue<Integer> right;public MedianFinder() {left = new PriorityQueue<>((a,b)->b-a); // 最大堆right = new PriorityQueue<>(); // 最小堆}public void addNum(int num) {if (left.size() == right.size()) {right.offer(num);left.offer(right.poll());} else {left.offer(num);right.offer(left.poll());}}public double findMedian() {if (left.size() > right.size()) {return left.peek();}return (left.peek() + right.peek()) / 2.0;}
}

链表排序

class Solution {public ListNode sortList(ListNode head) {if (head == null || head.next == null) return head;// 归并排序ListNode slow = head;ListNode fast = head.next;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}ListNode newHead = slow.next;slow.next = null;ListNode left = sortList(head);ListNode right = sortList(newHead);ListNode dm = new ListNode(0);ListNode curr = dm;while (left != null && right != null) {if (left.val < right.val) {curr.next = left;left = left.next;curr = curr.next; }else {curr.next = right;right = right.next;curr = curr.next;}}if (left != null) {curr.next = left;}if (right != null) {curr.next = right;}return dm.next;}
}

从一大段文本中找出TOP K 的高频词汇

题目: 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

class Solution {public int[] topKFrequent(int[] nums, int k) {PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->a[1]-b[1]);Map<Integer, Integer> map = new HashMap<>();for (int i = 0; i < nums.length; i++) {map.put(nums[i], map.getOrDefault(nums[i], 0)+1);}for (int key : map.keySet()) {if (pq.size() < k) {pq.offer(new int[]{key, map.get(key)});}else {if (pq.peek()[1] < map.get(key)) {pq.poll();pq.offer(new int[]{key, map.get(key)});}}}int[] ans = new int[k];for (int i = 0; i < k; i++) {ans[i] = pq.poll()[0];}return ans;}
}

题目: 给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

class Solution {public List<String> topKFrequent(String[] words, int k) {Map<String, Integer> map = new HashMap<>();for (int i = 0; i < words.length; i++) {map.put(words[i], map.getOrDefault(words[i], 0)+1);}PriorityQueue<String> pq = new PriorityQueue<>((a,b)->{//如果不同的单词有相同出现频率, 按字典顺序 排序if (map.get(a) == map.get(b)) {return b.compareTo(a);}return map.get(a) - map.get(b);});for (String s:map.keySet()) {pq.offer(s);if (pq.size() > k) {pq.poll();}}String[] ans = new String[k];for (int i = k-1; i >= 0; i--) {ans[i] = pq.poll();}return Arrays.asList(ans);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/76945.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模型压缩技术从零到一

模型压缩是深度学习中的重要技术&#xff0c;旨在减小模型尺寸和计算需求&#xff0c;特别适合在移动设备或嵌入式系统上部署。 要点 模型压缩技术可以显著减小模型尺寸和计算需求&#xff0c;适合资源受限设备。主要技术包括剪枝、量化、知识蒸馏、低秩分解和轻量级模型设计…

浮点数精度问题

目录 ieee754标准解决方法 和c语言一样&#xff0c;所有以ieee754标准的语言都有浮点数精度问题&#xff0c;js也有浮点数精度问题&#xff0c;并且因为是弱类型语言这个问题更严重&#xff0c;js的Number类型的数据都被视为浮点数 ieee754标准 js的数字类型就相当于c语言doub…

超大规模数据场景(思路)——面试高频算法题目

目录 用4KB内存寻找重复元素 从40个亿中产生不存在的整数【位】 如果只让用10MB空间存储&#xff1f; 初次遍历 二次遍历 用2GB内存在20亿个整数中查找出现次数最多的数【分块】 从亿万个URL中查找问题【分块 堆】 40亿个非负整数中找出现两次的数【位 不过多个位哈】 …

开源身份和访问管理方案之keycloak(三)keycloak健康检查(k8s)

文章目录 开源身份和访问管理方案之keycloak&#xff08;三&#xff09;keycloak健康检查启用运行状况检查 健康检查使用Kubernetes下健康检查Dockerfile 中 HEALTHCHECK 指令 健康检查Docker HEALTHCHECK 和 Kubernetes 探针 开源身份和访问管理方案之keycloak&#xff08;三&…

FATFS备忘

概述 FATFS文件系统可以挂载SD卡也可以挂载FLASH eMMC等设备 SD卡需要格式化为FAT32模式 块大小默认即可 移植 SD卡 SD卡扇区大小是 512B SD卡 SDIO模式 可以直接在cubeMX里一键设置 先设置好SD卡的设置 这个是选择支持中文 其余是默认 这个是检测引脚可以留空 当SD卡插入拔出…

唯美社区源码AM社区同款源码

源码介绍 唯美社区源码AM社区同款源码 后端修改application.properties文件内容为你的数据库 前端修改/config/config.js文件内容为你的后端地址 这两个文件里要修改的地方我已经用中文标注出来了 截图 源码免费下载 唯美社区源码AM社区同款源码

现代Web应用的多标签选择组件:设计哲学与工程实践

引言&#xff1a;标签选择的重要性与挑战 在信息爆炸时代&#xff0c;标签系统已成为内容组织的核心基础设施。研究表明&#xff1a; 使用标签系统的平台用户留存率提高35% 良好的标签选择体验可提升内容发现效率58% 80%的用户更倾向于使用提供可视化标签选择的应用 本文将…

P3799 小 Y 拼木棒

题目背景 上道题中&#xff0c;小 Y 斩了一地的木棒&#xff0c;现在她想要将木棒拼起来。 题目描述 有 n 根木棒&#xff0c;现在从中选 4 根&#xff0c;想要组成一个正三角形&#xff0c;问有几种选法&#xff1f; 答案对 1097 取模。 输入格式 第一行一个整数 n。 第…

Perl 条件语句

Perl 条件语句 引言 在编程中&#xff0c;条件语句是执行分支逻辑的关键部分。Perl 作为一种强大的脚本语言&#xff0c;提供了丰富的条件语句&#xff0c;使得开发者能够根据不同的条件执行不同的代码块。本文将深入探讨 Perl 中的条件语句&#xff0c;包括 if、unless、els…

流量特征分析-蚁剑流量分析

任务&#xff1a; 木马的连接密码是多少 这是分析蚁剑流量&#xff0c;可能是网站的&#xff0c;wireshark过滤http 追踪流http得到 1就是连接密码 flag{1}黑客执行的第一个命令是什么 取最后的执行命令。base64解密得 除了id不是蚁剑自带的命令&#xff0c;其他的都是&…

问题1:Sinal 4在开启PAC检查的设备崩溃

​ 问题信息 硬件不支持PAC(Pointer Authentication),此类错误就是signal 11的错误,崩溃信息如下: Build fingerprint: google/sdk_gphone64_arm64/emu64a:16/BP22.250221.010/13193326:userdebug/dev-keys Revision: 0 ABI: arm64 Timestamp: 2025-04-06 11:33:13.923…

FreeRTOS移植笔记:让操作系统在你的硬件上跑起来

一、为什么需要移植&#xff1f; FreeRTOS就像一套"操作系统积木"&#xff0c;但不同硬件平台&#xff08;如STM32、ESP32、AVR等&#xff09;的CPU架构和外设差异大&#xff0c;需要针对目标硬件做适配配置。移植工作就是让FreeRTOS能正确管理你的硬件资源。 二、…

【C++11(下)】—— 我与C++的不解之缘(三十二)

前言 随着 C11 的引入&#xff0c;现代 C 语言在语法层面上变得更加灵活、简洁。其中最受欢迎的新特性之一就是 lambda 表达式&#xff08;Lambda Expression&#xff09;&#xff0c;它让我们可以在函数内部直接定义匿名函数。配合 std::function 包装器 使用&#xff0c;可以…

JavaScript中的Proxy详解

1. 什么是Proxy&#xff1f; Proxy是ES6引入的一个强大特性&#xff0c;它允许你创建一个对象的代理&#xff0c;从而可以拦截和自定义该对象的基本操作。Proxy提供了一种机制&#xff0c;可以在对象的基本操作&#xff0c;如属性查找、赋值、枚举、函数调用等之前或之后执行自…

【git】VScode修改撤回文件总是出现.lh文件,在 ​所有 Git 项目 中全局忽略特定文件

VScode里面powershell被迫关闭 场景解决办法 场景 系统&#xff1a;Windows IDE&#xff1a;Visual Studio Code 一旦修改代码&#xff0c;就算撤回也会显示 解决办法 第一步&#xff1a;“C:\Users\用户名字.gitignore_global”&#xff1a;在该路径下新建.gitignore_glo…

为什么 LoRA 梯度是建立在全量参数 W 的梯度之上

&#x1f9e0; 首先搞清楚 LoRA 是怎么做微调的 我们原来要训练的参数矩阵是 W W W&#xff0c;但 LoRA 说&#xff1a; 别动 W&#xff0c;我在它旁边加一个低秩矩阵 Δ W U V \Delta W UV ΔWUV&#xff0c;只训练这个部分&#xff01; 也就是说&#xff0c;LoRA 用一个…

Nginx负载均衡时如何为指定ip配置固定服务器

大家在用Nginx做负载均衡时&#xff0c;一般是采用默认的weight权重指定或默认的平均分配实现后端服务器的路由&#xff0c;还有一种做法是通过ip_hash来自动计算进行后端服务器的路由&#xff0c;但最近遇到一个问题&#xff0c;就是希望大部分用户采用ip_hash自动分配后端服务…

Llama 4 家族:原生多模态 AI 创新的新时代开启

0 要点总结 Meta发布 Llama 4 系列的首批模型&#xff0c;帮用户打造更个性化多模态体验Llama 4 Scout 是有 170 亿激活参数、16 个专家模块的模型&#xff0c;同类中全球最强多模态模型&#xff0c;性能超越以往所有 Llama 系列模型&#xff0c;能在一张 NVIDIA H100 GPU 上运…

【硬件开发技巧】如何通过元器件丝印反查型号

目录 一、在线数据库查询 二、官方资料匹配 三、专业软件辅助 四、实物比对与场景推断 五、社区与人工支持 注意事项 一、在线数据库查询 专业元器件平台 Digi-Key、Mouser、ICMaster等平台支持直接输入丝印代码检索&#xff0c;可获取芯片型号、技术文档及替代型号。例如…

【算法/c++】利用中序遍历和后序遍历建二叉树

目录 题目&#xff1a;树的遍历前言题目来源树的数组存储基本思想存储规则示例 建树算法关键思路代码总代码 链表法 题目&#xff1a;树的遍历 前言 如果不是完全二叉树&#xff0c;使用数组模拟树&#xff0c;会很浪费空间。 题目来源 本题来自 PTA 天梯赛。 题目链接: 树…