小米算法高频题面经:快速排序原理、两数之和(哈希表一次遍历)、有效的括号(栈的应用)

34 阅读6分钟

小米算法高频题面试:小米Android开发覆盖MIUI系统定制、IoT设备互联。技术栈偏底层,面试官喜欢问系统级原理和性能数据。技术方向偏向MIUI定制、IoT互联。特色专项包括MIUI系统定制与IoT设备开发。今天8道题覆盖小米算法高频题面试核心考点。

Q1:快速排序原理?

分治:选pivot→根据pivot分区(左边小于pivot,右边大于)→递归排左右子数组。平均O(nlogn),最坏O(n²)(已排序数组+最后一个元素做pivot)。优化:随机选pivot或三数取中。

fun quickSort(arr: IntArray, low: Int = 0, high: Int = arr.lastIndex) {
    if (low >= high) return
    val pivot = partition(arr, low, high)
    quickSort(arr, low, pivot - 1); quickSort(arr, pivot + 1, high)
}

深度解析:从复杂度看,分治:选基准 partition 成两半再递归。平均 O(n log n),最坏 O(n²)(已有序且选端点的基准)。。常见变体与延伸包括:三数取中优化基准、堆排序(稳定 O(n log n))、TopK 用快排思想 O(n)。。实战要特别注意边界情况:近乎有序数据要随机化基准,否则退化。。面试官大概率会接着追问:怎么用快排思想在 O(n) 平均时间内找第 K 大?为什么平均是 O(n)?。

追问:为什么实际工程中快排比归并排序更常用?快排空间O(logn)(递归栈),归并O(n)(临时数组)——但快排不稳定。

Q2:两数之和(哈希表一次遍历)?

经典面试题:数组中找两个数使和等于target。暴力O(n²)→哈希表O(n)。关键优化:一次遍历——边遍历边查哈希表,当前元素之前如果有target-nums[i]在哈希表中就找到了。不需要先建哈希表再遍历。

fun twoSum(nums: IntArray, target: Int): IntArray {
    val map = HashMap<Int, Int>()
    for (i in nums.indices) {
        val complement = target - nums[i]
        if (complement in map) return intArrayOf(map[complement]!!, i)
        map[nums[i]] = i
    }
    return intArrayOf()
}

追问:为什么不能先建完整哈希表再查找?可以但多一次遍历。一次遍历法每次只查已遍历部分,更高效且避免重复元素覆盖问题。

Q3:有效的括号(栈的应用)?

判断括号字符串是否有效:每对括号必须正确闭合且嵌套正确。用栈:遇到左括号入栈,遇到右括号检查栈顶是否匹配的左括号——匹配则出栈,不匹配或栈空则无效。最后栈为空则有效。时间复杂度O(n),空间O(n)。

fun isValid(s: String): Boolean {
    val stack = ArrayDeque<Char>()
    val pairs = mapOf(')' to '(', ']' to '[', '}' to '{')
    for (c in s) {
        if (c in pairs.values) stack.addLast(c)
        else if (stack.isEmpty() || stack.removeLast() != pairs[c]) return false
    }
    return stack.isEmpty()
}

追问:为什么用栈?括号嵌套的LIFO特性——最后打开的括号最先关闭,天然匹配栈的后进先出。

Q4:环形链表检测(快慢指针)?

判断链表是否有环。快慢指针:slow每次走1步,fast每次走2步。如果有环,fast一定会在环中追上slow(相遇)。如果无环,fast会先到达null。时间复杂度O(n),空间O(1)——优于哈希表法的O(n)空间。进阶:找环入口——相遇后slow回到head,slow和fast同速前进,再次相遇点就是环入口。

fun hasCycle(head: ListNode?): Boolean {
    var slow = head; var fast = head
    while (fast?.next != null) {
        slow = slow?.next; fast = fast.next?.next
        if (slow == fast) return true
    }
    return false
}

追问:为什么快慢指针一定能相遇?如果有环,fast比slow每轮多走1步,在环中两者的距离每轮缩小1——一定会追上。

Q5:二叉树的最近公共祖先?

递归:如果root是p或q直接返回root;递归左子树和右子树;如果左右各返回一个(非null)说明p和q分布在两侧→root就是LCA;如果只有一侧返回非null说明p和q都在那一侧→返回那个非null。

fun lca(root: TreeNode?, p: TreeNode, q: TreeNode): TreeNode? {
    if (root == null || root == p || root == q) return root
    val left = lca(root.left, p, q); val right = lca(root.right, p, q)
    return when { left != null && right != null -> root; left != null -> left; else -> right }
}

追问:BST的LCA怎么做?利用BST有序性质——如果两个值都小于root在左子树递归,都大于在右子树递归,否则root就是LCA。

Q6:最大子数组和(Kadane算法)?

找数组中连续子数组的最大和。Kadane算法:遍历数组,维护currentSum和maxSum。currentSum = max(nums[i], currentSum + nums[i])——如果前面累加的和不如当前元素本身大,就重新开始。maxSum = max(maxSum, currentSum)。一次遍历O(n),空间O(1)。

fun maxSubArray(nums: IntArray): Int {
    var curSum = nums[0]
    var maxSum = nums[0]
    for (i in 1 until nums.size) {
        curSum = max(nums[i], curSum + nums[i])
        maxSum = max(maxSum, curSum)
    }
    return maxSum
}

追问:Kadane算法的直觉是什么?如果前面的累加是负贡献(让当前元素变小),不如丢弃重新开始——贪心思想。

Q7:合并两个有序链表?

递归:比较两个头节点的大小,小的作为新头,next指向递归合并剩余部分。迭代:用dummy哨兵,每次取两链表中较小的接到结果链表。

fun mergeTwo(l1: ListNode?, l2: ListNode?): ListNode? =
    when { l1 == null -> l2; l2 == null -> l1
        l1.v < l2.v -> { l1.next = mergeTwo(l1.next, l2); l1 }
        else -> { l2.next = mergeTwo(l1, l2.next); l2 } }

追问:合并K个有序链表的思路?用最小堆(O(nlogk))或分治两两合并。

Q8:滑动窗口—无重复字符的最长子串?

双指针left/right维护窗口,HashMap记录字符最后出现位置。right右移:如果当前字符在窗口内出现过,left跳到上次出现位置+1。右移时更新maxLen。时间复杂度O(n)。

fun lengthOfLongestSubstring(s: String): Int { var l = 0; var max = 0
    val map = mutableMapOf<Char, Int>()
    for (r in s.indices) { val c = s[r]; if (c in map) l = max(l, map[c]!! + 1)
        map[c] = r; max = max(max, r - l + 1) }; return max }

追问:滑动窗口的核心思想?用两个指针维护一个满足条件的窗口,右边界扩张,左边界收缩。

下一篇进入小米特色专项——MIUI的GPU Turbo如何在Andro、MIUI如何实现IoT设备互联、MIUI的自由窗口(小窗)实现原理。

觉得有用的同学扣1,你面试被追问最狠的是哪道题?

本系列连载中,关注不迷路,下一篇:小米特色专项面经:MIUI的GPU Turbo如何在Andro、MIUI如何实现IoT设备互联、MIUI的自由窗口(小窗)实现原理

系列简介:Android大厂面经连载,覆盖字节跳动、腾讯、阿里、美团等40+企业,从初级到架构师全岗位覆盖。每篇文章包含真实面试题+详细答案+代码示例,帮你拿到大厂Offer。