topcode【随机算法题】【2026.5.16打卡-java版本】

695.岛屿的最大面积

要点:bfs!! 标记要变1->0

java 复制代码
class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        int n = grid.length;
        int m = grid[0].length;
        int max = 0;
        for(int i = 0; i < n; i++){
            for(int j =0; j < m; j++){
                if(grid[i][j] == 1){
                    int ans = bfs(i, j, grid);
                    max = Math.max(ans, max);
                }
            }
        }

        return max;
        
    }

    public int bfs(int n, int m, int[][] grid){

        if(n < 0 || n >= grid.length || m < 0 || m >= grid[0].length || grid[n][m] == 0 ){
            return 0;
        }

        grid[n][m] =0;

        int[][] dirs = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};
        int res = 1;
        for(int[] dir : dirs){
            res += bfs(n+dir[0], m+dir[1], grid);
        }

        return res;
    }






}

122.买卖股票的最佳时机

贪心

java 复制代码
class Solution {
    public int maxProfit(int[] prices) {
        int max = 0;
        for(int i = 1; i < prices.length; i++){
            if(prices[i] > prices[i-1]){
                max += prices[i] - prices[i-1];
            }
        }

        return max;
    }
}

110.平衡二叉树

dfs

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //dfs
    public boolean isBalanced(TreeNode root) {

        return getHeight(root) != -1;

    }

    public int getHeight(TreeNode root){
        if(root == null){
            return 0;
        }

        int left = getHeight(root.left);
        int right = getHeight(root.right);

        if(left == -1 || right == -1 || Math.abs(left-right) > 1){
            return -1;
        }

        return Math.max(left, right) +1;
    }
}

234.回文链表

要点:中间点+反转链表

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        ListNode mid = middle(head);
        ListNode head2 = reverse(mid);

        while(head2 != null){
            if(head.val == head2.val){
                head = head.next;
                head2 = head2.next;
            }else{
                return false;
            }
        }

        return true;
        
    }

    public ListNode middle(ListNode head){
        ListNode fast = head;
        ListNode slow = head;

        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }

        return slow;
    }

    public ListNode reverse(ListNode head){

        //要是null
        ListNode pre = null;
        ListNode curr = head;

        while(curr != null){
            ListNode next = curr.next;
            curr.next = pre;
            pre =curr;
            curr =next;
        }

        return pre;
    }
}

随机基础知识

一、索引(必问,最高频)

索引是什么?为什么要用 B+ 树?联合索引的最左前缀原则是怎么回事?

面试官为什么这么问?

索引是数据库优化的核心,我把它放第一题就是要看你是否真正理解数据结构的选择,而不是背一个"索引就像书的目录"。我想听你说清为什么 MySQL 选择了 B+ 树,以及怎么写 SQL 才能用上你建的索引。

希望听到怎样的回答:

  • 索引是帮助 MySQL 高效查询的数据结构,类比书的目录。
  • 为什么用 B+ 树:非叶子节点只存索引,不存数据,树更矮胖,减少磁盘 IO ;叶子节点形成有序双向链表,范围查询高效
  • 联合索引的最左前缀原则:索引 (a, b, c) 相当于建了 (a)、(a,b)、(a,b,c) 三个索引;查询条件缺最左边的列,索引失效。
  • 举例:where b=1 不走索引;where a=1 and c=2 只会用到 a,c 用不了;where a=1 and b>2 and c=3 中 c 也用不了,因为范围查询会截断。
  • 能加一句"我们项目里用户表的手机号建了唯一索引,面试题目的分类和难度字段建了联合索引"会非常加分。

候选人

好的,我从这三个问题依次展开讲。

第一部分:索引是什么。

索引是数据库表中一种用于加速数据检索的数据结构。类比书的目录,没有目录要查一个关键词得逐页翻整本书,有了目录可以直接定位到对应的页码。在 MySQL 中,索引同样避免全表扫描,通过数据结构快速定位到目标数据所在的磁盘位置,显著减少磁盘 IO 次数,提升查询性能。索引本身存储在磁盘上,有自己的文件结构。

第二部分:为什么用 B+ 树。

MySQL 选择 B+ 树而不是哈希表或二叉树,核心原因有两个:磁盘 IO 优化范围查询支持

先看哈希表。哈希表对等值查询非常快,O(1) 时间就能定位数据。但它有两个致命问题:一是不支持范围查询,where id > 10 and id < 100 这种条件,哈希表只能全表扫描,因为哈希值之间没有顺序关系;二是哈希冲突严重时性能下降。数据库查询中最常见的不是单条精确查询,而是范围查询和排序,所以哈希表不适合。

再看二叉树。二叉树在数据有序插入时会退化成链表,查询从 O(log n) 变成 O(n)。即使平衡二叉树如红黑树可以自平衡,但每个节点只有两个子节点,当数据量达千万级别时,树的高度会非常大。树的高度直接影响磁盘 IO 次数,因为数据库中每个节点存储在磁盘的不同页中,访问一个节点就是一次 IO,高度越大性能越差。

B 树是多路平衡查找树,每个节点可以有多个子节点,树的高度远低于二叉树。但 B 树在非叶子节点中也存储数据,导致每个节点能存的索引数量变少,树的分叉数降低、高度增加。并且 B 树在范围查询时需要在各层之间来回遍历,效率较差。

B+ 树对 B 树的改进正是针对这两点。第一,B+ 树的非叶子节点只存储键值(索引列的值)和子节点指针 ,不存储实际数据行。这样一个节点可以容纳很多索引条目,树的分叉数极大,高度变得非常矮。千万级数据的 B+ 树高度通常只有 3~4 层,一次查询只需 3~4 次磁盘 IO。第二,B+ 树所有数据记录都存放在叶子节点中,叶子节点之间用双向链表串联。等值查询可以快速到达叶子节点,范围查询只需一次定位到起始位置,然后顺着链表向后遍历即可,效率非常高。

所以在 MySQL 的 InnoDB 引擎中,表根据主键构建聚簇索引,就用 B+ 树。聚簇索引的叶子节点直接存放整行数据。非聚簇索引的叶节点存放的是索引列的值加主键值,需要回表取完整行数据。

第三部分:联合索引的最左前缀原则。

联合索引是最常在面试中被追问的索引类型。它在单个索引中包含多个列,索引按定义的列顺序构建 B+ 树。比如定义一个联合索引 (a, b, c),B+ 树的节点先按 a 排序,a 相同时按 b 排序,b 相同时再按 c 排序。

最左前缀原则规定:联合索引 (a, b, c) 其实相当于创建了 (a)(a, b)(a, b, c) 三个索引,但不能跳过最左边的列。具体来说:

  • where a = 1 可以走索引,匹配列 a。
  • where a = 1 and b = 2 可以走索引,匹配 a 和 b。
  • where a = 1 and b = 2 and c = 3 可以走索引,匹配所有三列。
  • where b = 2 无法走索引,因为缺少最左列 a。
  • where b = 2 and c = 3 同样无法走索引。
  • where a = 1 and c = 3 只能用到 a 这个索引,c 用不了,因为中间跳过了 b。

范围查询截断问题 :当最左前缀匹配到范围查询时,后续的列会失效。where a = 1 and b > 2 and c = 3 中,索引只能用到 a 和 b,c 用不了。因为 b 使用了范围条件,B+ 树在 a 相同的分组内按 b 排序,但 b 的范围匹配出多条记录后,这些记录的 c 是分散不连续的,无法利用 b 后面的 c 列继续快速定位。这就是典型的最左前缀匹配中断。

所以在创建联合索引时,把等值查询条件中的最常用字段放在最左侧,同时在涉及范围查询的字段后面不再附加其它等值过滤字段。查询条件的顺序不影响索引使用,MySQL 优化器会自动调整 WHERE 条件内部顺序来匹配最左前缀,关键是索引列定义的顺序是否完整包含了查询条件的最左边部分。

第四部分:项目中的实际应用。

我项目里的用户表在手机号字段上建了唯一索引,保证手机号全局不重复,同时支持通过手机号快速查询用户。面试题目的表在分类和难度字段上建了联合索引 (category, difficulty),因为所有查询列表的入口条件都是按分类筛选再按难度排序,建立这个联合索引后查询时间从几百毫秒降到毫秒级别。

设计索引时会综合考量字段的区分度和查询频率,高区分度的字段放在前面能快速缩小数据范围。

总结一句话:索引是用空间换时间的查询优化方案,MySQL 选择 B+ 树是因为它的矮胖结构减少磁盘 IO,并且双向链表让范围查询同样高效;联合索引按最左前缀原则使用,跳过最左列就无法利用索引,范围查询会截断后续列的索引使用。项目里根据查询入口和字段区分度来设计索引,是数据库优化最基本也是最有效的手段。

碎碎念:后续会更新每天学习的八股和算法 题,暑假实习找不到了,开始准备秋招的第6天。努力连续更新100天!今天确实没学啥,玩了一天,不管适当休息就当,加油加油!!把大体思路重新梳理了一遍。严格按计划学习吧。不要觉得休息日就放松警惕了!!!!

相关推荐
摇滚侠1 小时前
SpringBoot 面试题 真正的 offer 偏方 Java 基础 Java 高级
java·spring boot·后端
Shan12051 小时前
广度优先搜索之层序遍历
数据结构·算法·宽度优先
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第58题】【JVM篇】第18题:讲一下三色标记
java·开发语言·jvm
huaiixinsi1 小时前
Java 后端面试高频题整理(02)
java·开发语言·spring·面试·职场和发展·架构·maven
SilentSamsara1 小时前
自定义上下文管理器实战:数据库连接池、文件锁与超时控制
开发语言·python·算法·青少年编程
清辞8531 小时前
集合竞价选股程序开发学习
数据结构
吃着火锅x唱着歌1 小时前
LeetCode 503.下一个更大元素II
算法·leetcode·职场和发展
_深海凉_1 小时前
LeetCode热题100-将有序数组转换为二叉搜索树
数据结构·算法·leetcode
我只想困告1 小时前
day02-RabbitMQ 2026-05-14
java·spring·rabbitmq