MST

星途 面试题库

面试题:Go语言Map键值对复杂自定义排序及性能优化

给定一个map[string][]int类型的映射,其中每个值是一个整数切片。要求按照切片中所有整数的和进行排序,如果和相同,则按照切片的长度升序排序。请设计一个高效的自定义排序方案,不仅要给出实现代码,还需要分析排序过程中的时间复杂度和空间复杂度,并说明如何进行性能优化。
45.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sort"
)

type BySumAndLen struct {
    m map[string][]int
    keys []string
}

func (b BySumAndLen) Len() int {
    return len(b.keys)
}

func (b BySumAndLen) Less(i, j int) bool {
    sumI := 0
    for _, v := range b.m[b.keys[i]] {
        sumI += v
    }
    sumJ := 0
    for _, v := range b.m[b.keys[j]] {
        sumJ += v
    }
    if sumI != sumJ {
        return sumI < sumJ
    }
    return len(b.m[b.keys[i]]) < len(b.m[b.keys[j]])
}

func (b BySumAndLen) Swap(i, j int) {
    b.keys[i], b.keys[j] = b.keys[j], b.keys[i]
}

func sortMapBySumAndLen(m map[string][]int) []string {
    var keys []string
    for k := range m {
        keys = append(keys, k)
    }
    sorter := BySumAndLen{m, keys}
    sort.Sort(sorter)
    return sorter.keys
}

时间复杂度分析

  1. 计算总和:对于每个切片,计算其总和的时间复杂度为 (O(n)),其中 (n) 是切片中元素的个数。假设总共有 (m) 个切片,平均每个切片长度为 (n),那么计算所有切片总和的时间复杂度为 (O(mn))。
  2. 排序:Go 语言中 sort.Sort 使用的是快速排序,平均时间复杂度为 (O(m \log m)),其中 (m) 是切片的数量。

综合起来,总的时间复杂度为 (O(mn + m \log m))。

空间复杂度分析

  1. 存储键:我们创建了一个切片来存储所有的键,其空间复杂度为 (O(m)),其中 (m) 是映射中键值对的数量。
  2. 排序过程:快速排序的空间复杂度在平均情况下为 (O(\log m)),最坏情况下为 (O(m))。

综合起来,总的空间复杂度为 (O(m))。

性能优化

  1. 预计算总和:在构建 BySumAndLen 结构体时,可以预先计算每个切片的总和并存储起来,这样在 Less 方法中就不需要每次都重新计算总和,从而将计算总和的时间复杂度从 (O(mn)) 降低到 (O(m)),整体时间复杂度变为 (O(m + m \log m)),近似为 (O(m \log m))。
  2. 减少内存分配:尽量减少在 Less 方法中的临时变量分配,例如可以预先分配好存储总和的变量,避免每次调用 Less 时都进行内存分配。