当前位置: 首页 > news >正文

2025高频面试算法总结篇【其他】

文章目录

  • 直接刷题链接直达
  • LRU Cache
  • 买卖股票的最佳时机系列
  • 实现一个HashMap
  • 环形链表
  • 寻找重复数
  • 缺失的第一个正数
  • 螺旋矩阵
  • 字符串相乘
  • 分发糖果


直接刷题链接直达

  • LRU Cache
    • 头尾两个伪节点(避免判断) + 双向链表
    • 146. LRU 缓存
  • 买卖股票的最佳时机系列
    • 121. 买卖股票的最佳时机
  • 实现一个HashMap
    • 要求:1. 定义内部存储结构; 2.实现 insert(key, value) 和 remove(key);3.不能使用任何Java集合框架。
    • 706. 设计哈希映射
  • 求给定区间内子区间的最大值(区间内最小值*区间元素相加)
    • 要求时间复杂度O(n)
    • 原题
  • 斐波那契数列的尾递归实现
    • 面试官原意是斐波那契的递归实现如何优化
    • 尾递归就是把当前的运算结果(或路径)放在参数里传给下层函数
    • 递归与尾递归总结
  • 1到10000有多少个数字7
    • 答案 :4000
    • 腾讯面试题-0到9999这1万个数中有多少个数字7
  • 给定精度(如小数点后10位),写一个函数求根号2的具体值
    • 牛顿法,详见 如何通俗易懂地讲解牛顿迭代法求开方?数值分析?
    • 69. x 的平方根
  • 给定一个乱序数组[0,100],替换其中一个数,找出这个被替换的数
    • 类似 142. 环形链表 II 思路,重复数字会形成环,双指针寻找
    • 287. 寻找重复数
  • 缺失的第一个正数
    • 41. 缺失的第一个正数
  • 顺时针打印矩阵(星环)
    • 54. 螺旋矩阵
  • 实现一个int转中文表示的函数,同时设计测试用例
    • 定界数据范围 + 梳理演变规则(以“万”为节,化繁为简,以及“零”如何处理)
    • 数字(int型范围内正整数)和中文的相互转换
  • 100盏灯问题
    • 面试题—100盏灯问题
  • 给定一个数组,一个闭区间[n,m],给出该数组中所有最大值在闭区间中的连续子数组数目
    • 要求时间复杂度O(n)
    • 如 [2,1,4,3],[2,3],有[2],[2,1],[3],返回3
  • 字符串相乘
    • 43. 字符串相乘
  • 用Java实现一个String转Map(Map<String,Object>)的函数,不能使用String的split和第三方库
  • 整数中1出现的次数(从1到n中1出现的次数)
    • 233. 数字 1 的个数
  • 单词接龙
    • 广度优先 --> 队列 + 暴力搜索(遍历过的单词删除),视频讲解见 花花酱 LeetCode 127. Word Ladder - 刷题找工作 EP71
    • 127. 单词接龙
  • 分数到小数
    • 将除法过程代码化
    • 166. 分数到小数
  • 只出现一次的数字
    • 136. 只出现一次的数字
  • 分糖果
    • 从左至右扫一遍,再从右至左扫一遍,取两遍中的最大值
    • 135. 分发糖果
  • 实现一个命令行逆波兰计算器
    • CommandLineRPN
  • Largest M-aligned Subset
    • Microsoft | OA 2020 | Largest M-aligned Subset

LRU Cache

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

class LRUCache {private final int capacity;// 双向链表 put 操作 会把数据放表尾-》最近最久未使用在表头(remove去掉表头)private final LinkedHashMap<Integer, Integer> data;public LRUCache(int capacity) {this.capacity = capacity;this.data = new LinkedHashMap<>(capacity);}public int get(int key) {// 这个key存在 =》 删除,放表尾if (data.containsKey(key)) {Integer value = data.remove(key);data.put(key, value);return value;}return -1;}public void put(int key, int value) {if (data.containsKey(key)) {data.remove(key);data.put(key, value);return;}if (data.size() == capacity) {// 删除表头元素data.remove(data.keySet().iterator().next());}data.put(key, value);}
}

补充:

class LRUCache {private static class Node {int key, value;Node prev, next;Node(int k, int v) {key = k;value = v;}}private final int capacity;private final Node dummy = new Node(0, 0); // 哨兵节点private final Map<Integer, Node> keyToNode = new HashMap<>();public LRUCache(int capacity) {this.capacity = capacity;dummy.prev = dummy;dummy.next = dummy;}public int get(int key) {Node node = getNode(key); // getNode 会把对应节点移到链表头部return node != null ? node.value : -1;}public void put(int key, int value) {Node node = getNode(key);if (node != null) { // 有这本书node.value = value; // 更新 valuereturn;}node = new Node(key, value); // 新书keyToNode.put(key, node);pushFront(node); // 放在最上面if (keyToNode.size() > capacity) { // 书太多了Node backNode = dummy.prev;keyToNode.remove(backNode.key);remove(backNode); // 去掉最后一本书}}// 获取 key 对应的节点,同时把该节点移到链表头部private Node getNode(int key) {if (!keyToNode.containsKey(key)) { // 没有这本书return null;}Node node = keyToNode.get(key); // 有这本书remove(node); // 把这本书抽出来pushFront(node); // 放在最上面return node;}// 删除一个节点(抽出一本书)private void remove(Node x) {x.prev.next = x.next;x.next.prev = x.prev;}// 在链表头添加一个节点(把一本书放在最上面)private void pushFront(Node x) {x.prev = dummy;x.next = dummy.next;x.prev.next = x;x.next.prev = x;}
}

买卖股票的最佳时机系列

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

class Solution {public int maxProfit(int[] prices) {int mp = Integer.MAX_VALUE;int max = Integer.MIN_VALUE;for (int p:prices) {if (p < mp) {mp = p;}max = Math.max(max, p - mp);}return max;}
}

实现一个HashMap

public class MyHashMap {int capacity = 16;class Node {int key;int value;Node next;public Node() {this.next = null;}public Node(int key, int value) {this.key = key;this.value = value;this.next = null;}}Node[] bucket;public MyHashMap() {this.bucket = new Node[capacity];}public void put(int key, int value) {int i = key % capacity;if (bucket[i] == null) {bucket[i] = new Node(key, value);return;}Node temp = bucket[i];if (temp.key == key) {temp.value = value;return;}while (temp.next != null) {if (temp.next.key == key) {temp.next.value = value; // fix herereturn;}temp = temp.next;}temp.next = new Node(key, value); // insert at end}public int get(int key) {int i = key % capacity;Node temp = bucket[i];while (temp != null) {if (temp.key == key) {return temp.value;}temp = temp.next;}return -1; // not found}public void remove(int key) {int i = key % capacity;Node temp = bucket[i];if (temp == null) return;if (temp.key == key) {bucket[i] = temp.next;return;}while (temp.next != null) {if (temp.next.key == key) {temp.next = temp.next.next;return;}temp = temp.next;}}
}

环形链表

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

思路:

  • 快慢指针 判断是否有环。
  • 有环,快指针=第一个节点,然后两个指针向下遍历,相遇的点就是开始入环的第一个节点。
public class Solution {public ListNode detectCycle(ListNode head) {if (head == null || head.next == null) return null;ListNode fast = head;ListNode slow = head;// 快慢指针:判断是否有环while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (fast == slow) {break;}}// 没有环if (fast == null || fast.next == null) {return null;}// 有环:重新让 fast 从头走,和 slow 一起一步一步走,相遇点就是环的入口fast = head;while (fast != slow) {fast = fast.next;slow = slow.next;}return slow;}
}

寻找重复数

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

将数组视为链表,nums[i] 表示“指针”,指向 nums[nums[i]]。

💡 思路:
把 nums 看成链表,数组下标是节点编号,值是指针指向的下一个节点;

因为有重复值,所以一定有“环”;

问题转化为:找这个链表的“环入口”,这就是“重复的数”。

public class Solution {public int findDuplicate(int[] nums) {// 初始化快慢指针int slow = nums[0];int fast = nums[0];// 第一步:快慢指针找相遇点(在环中)do {slow = nums[slow];fast = nums[nums[fast]];} while (slow != fast);// 第二步:找环的入口(即重复的数字)fast = nums[0];while (fast != slow) {fast = nums[fast];slow = nums[slow];}return slow; // or fast}
}

缺失的第一个正数

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

思想:把每个数字放到它“该去的位置”,然后再检查哪个位置缺少那个数字。

class Solution {public int firstMissingPositive(int[] nums) {// 把每个数字放到它“该去的位置”,然后再检查哪个位置缺少那个数字。int i = 0;while (i < nums.length) {if (nums[i] != i+1 && nums[i] > 0 && nums[i] <= nums.length && nums[nums[i] - 1] != nums[i]) {int temp = nums[nums[i]-1];nums[nums[i]-1] = nums[i];nums[i] = temp; }else {i++;}}for (int k = 0; k < nums.length; k++) {if (nums[k] != k + 1) {return k+1;}}return nums.length + 1;}
}

螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

class Solution {public List<Integer> spiralOrder(int[][] matrix) {List<Integer> ans = new ArrayList<>();int m = matrix.length;int n = matrix[0].length;// 边界int l = 0, r = n - 1, t = 0, b = m - 1;while (l <= r && t <= m) {// 左 到 右for (int i = l; i <= r; i++) {ans.add(matrix[t][i]);}// 边界判断if (++t > b) break;// 上 到 下for (int i = t; i <= b; i++) {ans.add(matrix[i][r]);}if (--r < l) break;// 右 到 左for (int i = r; i >= l; i--) {ans.add(matrix[b][i]);}if (--b < t) break;// 从 下 到 上for (int i = b; i >= t;i--) {ans.add(matrix[i][l]);}if (++l > r) break;}return ans;}}

字符串相乘

给定两个以字符串形式表示的非负整数 num1num2,返回 num1num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

class Solution {public String multiply(String num1, String num2) {if ("0".equals(num1) || "0".equals(num2)) return "0";int m = num1.length();int n = num2.length();int[] res = new int[m + n]; // 最多 m+n 位for (int i = m - 1; i >= 0; i--) {int a = num1.charAt(i) - '0';for (int j = n-1; j >= 0; j--) {int b = num2.charAt(j) - '0';int sum = res[i+j+1] + a*b;res[i+j+1] = sum % 10;res[i+j] += sum/10; // +=}}// 转换成字符串,去掉前导0StringBuilder sb = new StringBuilder();for (int num : res) {if (sb.length() == 0 && num == 0) continue;sb.append(num);}return sb.toString();}
}

分发糖果

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

class Solution {public int candy(int[] ratings) {int n = ratings.length;int[] candys = new int[n];// 每个孩子至少分配到 1 个糖果Arrays.fill(candys, 1);// 从 左 到 右 遍历:相邻两个孩子评分更高的孩子会获得更多的糖果for (int i = 1; i < n; i++) {if (ratings[i] > ratings[i-1]) {candys[i] = candys[i-1]+1;}}// 从 右 到 左 遍历:相邻两个孩子评分更高的孩子会获得更多的糖果for (int i = n-2; i >= 0; i--) {if (ratings[i] > ratings[i+1]) {candys[i] = Math.max(candys[i], candys[i+1]+1);}}int sum = 0;for (int i = 0; i < n; i++) {sum += candys[i];}return sum;}
}

相关文章:

  • ADB->查看某个应用的版本信息
  • 性能比拼: Nginx vs Apache
  • vdso内核与glibc配合的相关逻辑分析
  • IDEA打不开、打开报错
  • 【Easylive】手动实现分布式事务解决方案流程解析
  • 【Flask】Explore-Flask:早期 Flask 生态的实用指南
  • 多模态大语言模型arxiv论文略读(三十三)
  • 【产品经理思维】
  • 多级缓存架构,让系统更快的跑起来!
  • 特伦斯智慧钢琴评测:如何用科技重塑钢琴学习新体验
  • Cribl 利用表向event 中插入相应的字段-example-01
  • C++入门语法
  • FreeRTOS中的优先级翻转问题及其解决方案:互斥信号量详解
  • 第十四届蓝桥杯 2023 C/C++组 平方差
  • 设计模式 建造者模式
  • Pycharm(九)函数的闭包、装饰器
  • compat-openssl10和libnsl下载安装
  • Java高效合并Excel报表实战:GcExcel让数据处理更简单
  • 靠华为脱胎换骨,但赛力斯仍需要Plan B
  • MySQL访问权限授权问题
  • 南阳市委副书记、政法委书记金浩任内落马
  • 国际市场开心果价格上涨35%,背后助力是一条点击过亿的短视频
  • 天工摘得全球首个人形机器人半马冠军:中国机器人产业正努力跑向人机共生社会
  • 中国船协发布关于美对华造船业实施限制措施的严正声明
  • 成都一医院孕妇产下七胞胎?涉事医院辟谣:信息不实已举报
  • 刘国梁:奥运会乒乓球项目增至六金,国乒机遇与挑战并存