[算法篇]怎么和媳妇儿讲算法的复杂度?

123 阅读3分钟

铺垫下前奏

今天晚上睡觉前洗了衣服, 媳妇儿提醒我晒衣服. 顺便,攒了2各个星期的袜子终于要洗了.

晒袜子的过程中烦死, 要把一对的袜子放在一起晒, 难道要把袜子先:分类好,再挂到挂钩上? 之前淘宝上买的袜子挂钩激发了我的灵感. 这样收起来下次穿的时候就不会找不到公母了.

image.png

那么这个挂钩看起来是不是很像一个数组? 而下面的挂钩就是"对数组元素的引用".

进入正题

那么怎么利用算法逻辑让我的袜子快速而又不用无聊的有序挂完?

  1. 从盆里随便抓一只袜子先挂到钩子上.
  2. 再取一只, 如果已经在钩子上面已经有(这一款)了, 那么配对;如果没有, 走步骤(1)
  3. 循环(1),(2)步骤. 那么很快就挂完了. 如果不这么做就需要先分类. 再挂. 在leetcode上第一道算法题就是对这个逻辑的抽象.

在数组中找到 2 个数之和等于给定值的数字,结果返回 2 个数字在数组中的下标。

package leetcode
func twoSum(nums []int, target int) []int {
    m := make(map[int]int)
    for i := 0; i < len(nums); i++ {
      another := target - nums[i]
      if _, ok := m[another]; ok {
         return []int{m[another], i} 
      }
      m[nums[i]] = i 
    }
    return nil  
}

这道题最优的做法时间复杂度是 O(n)。 顺序扫描数组,对每⼀个元素,在 map 中找能组合给定值的另⼀半数字,如果找到了,直接返回 2 个 数字的下标即可。如果找不到,就把这个数字存⼊ map 中,等待扫到“另⼀半”数字的时候,再取出来返 回结果。

有的朋友就喜欢抬杠了, 我就洗两双袜子还要像你一样写代码计算一番? 其实朋友, 艺术和数学都来源于生活. 我们应该保持一个对生活的好奇心.

话题延伸

那么就到此为止了吗? 当然不是, 生活和项目需求有一个共同点: 情况总是变化的!

2双袜子, 5双袜子, 10双袜子都没事. 如果洗的是100双袜子呢? 那么就需要对我们的算法模型做下优化了.

一个衣架挂钩不下那么多袜子了(比如单机内存一下子存不下100亿个整数).

那么就需要多买几个衣架了(分布式部署), 如果袜子干了收起来就把挂钩借给邻居用(云原生扩缩容/资源限制+合理调度)

一双袜子的第一只袜子先挂到哪个勾上去呢(数据落盘的负载均衡策略)?

那就先对颜色进行分类编号:浅色到深色0/1/2/3以此类推.按照颜色对个数取模来决定顺序(一致性哈希).

这个话题就到这里结束吧, 估计太多概念给媳妇儿接受不了哈哈. 而且其中很多算法细节是值得推敲的, 先用"糙理"来给我培养下算法的感觉.