CodingTour
ARTS #161

Algorithm

本周选择的算法题是:Minimum Moves to Equal Array Elements II

规则

Given an integer array nums of size n, return the minimum number of moves required to make all array elements equal.

In one move, you can increment or decrement an element of the array by 1.

Test cases are designed so that the answer will fit in a 32-bit integer.

Example 1:

Input: nums = [1,2,3]
Output: 2
Explanation:
Only two moves are needed (remember each move increments or decrements one element):
[1,2,3]  =>  [2,2,3]  =>  [2,2,2]

Example 2:

Input: nums = [1,10,2,9]
Output: 16

Constraints:

  • n == nums.length
  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

Solution

impl Solution {
    pub fn min_moves2(mut nums: Vec<i32>) -> i32 {
        nums.sort();
        
        let median = nums[nums.len() / 2];
        nums.into_iter().fold(0, |accum, num| {
            accum + (num - median).abs()
        })
    }
}

Review

Object-Oriented Programming in Rust

Rust 虽然不是一门 OOP 语言,但它有自己的方式优雅的解决编程中的问题,比如 Enum 的每个成员可以定义为不同的类型:

enum Animal {
    Dog,
    Cat = 0,
    Pig { cooked: bool },
    Cow(String),
    Goat(Goat),
}
struct Goat {
    age: u32,
}

配合模式匹配执行不同的策略:

impl Animal {
    fn speak(&self) {
        match self {
            Animal::Dog(_) => println!("Woof!"),
            Animal::Cat(_) => println!("Meow!"),
            Animal::Pig(_) => println!("Oink!"),
        }
    }
}

Traits 除了申明还可以定义默认实现:

trait AABB {
    fn min(&self) -> Vec3;
  
    fn max(&self) -> Vec3;

    fn collision(&self, other: &impl AABB, vel: &Vec3) -> Vec3 {
        // default implementation
    }
}

尽管可以模仿 OOP,但其背后的设计理念完全不同,拿 trait 来说,它是语义是 “要实现 A,你必须也实现 B”,而不是 “当你实现 A 时,你会自动实现 B”,后者是继承和子类型背后的理念。

OOP 思想归结为想要做两件事:

  • 定义一组公共类型,并允许子类化它们
  • 强制一个对象提供某些方法或变量

Rust Book 17 章的写法很聪明,他不是上来就说 Rust 和 OOP 的关系,而是先梳理编程过程中要解决的问题是什么,再列出 OOP 是如何解决这些问题的,最后告诉大家如何在 Rust 下解决这些问题 — 而不是 Rust 下如何实现 OOP。这种写法既避免了语言、模式之争,也告诉了读者在 Rust 下解决这些问题的最佳实践是什么,是非常聪明的做法。

Tip

iCloud Drive 状态莫名卡在上传中,用 killall bird 修复。

Share

ee 闭门晚宴笔记

晚宴围绕今年最火的「降本增效」展开,主要是三个问题:

  • 如何理解成本和效率
  • 怎样证明效率确实有提高
  • 大型企业具体是怎么做的

如何理解成本和效率

首先降本增效重点是增效,不能为了降本而去卷数字,数字有太多方法可以达到,为了避免没意义的数字,降本应该要有具体的目标和不同的手段,如上云、统一容器调度等。

而且国内外企业成本来源不同:

  • 国外 - 人力成本高,能用机器自动化解决的就尽量堆机器
  • 国内 - 人力成本低,能堆人解决的就堆人,衬托出机器成本高

但机器成本不是关注的重点,成本应该总是从业务角度来考虑,业务做的好坏取决于企业中的组织是如何协作的,所以成本的关键是:

  • 沟通成本
  • 决策成本
  • 试错成本

具体的问题还是需要人去解决,当下环境特别考验大家对人才的态度,总的来说,要用最高的价格招更贵的人:

  • 重视人才密度,在寒冬时积累人力
  • 大厂人才平时股票多,根本挖不动,寒冬才是下手的最好时机
  • 一个合适的人抵得上数十个人,一个团队核心也就那两个人
  • 没有春天不会到来,重点是冬天积累到了东西
  • 春天来临时,冬天的储备就是下个周期最大的资产

此外,效率要有具体的需求来支撑,比如一个蛋糕店,一天卖100个蛋糕,每个蛋糕假设利润是一块钱,那如何把蛋糕的产能提高10倍呢,是否意味着更高的利润?不一定,还要看蛋糕店外有多少人在排队,效率提升是无止境的,关键要有提高效率的需求。

延伸到需求,怎么确认一个需求的价值?两个建议:

  • 要跳出需求看需求

  • 照着听,别照着做

确认好方向,持续努力,过程中淡定面对质疑。

怎样证明效率确实有提高

「证明」是一件挺危险的事,如果效能团队需要证明自身的价值,其实侧面也说明了没有价值,至少业务没有感受到。和成本优化一样,假如效能团队也开始卷数字,比如研发工具的覆盖率、渗透率等指标,这看似好衡量(有数字,而且总有方法提高它),但不一定对业务有实际的帮助,效能团队的价值应该由业务给到,而不是自身证明。

效能团队的“第一性原理”:

  • 更高效 - 价值流动过程必须高效顺畅,阻力越小越好
  • 更高质量 - 如果质量不行,流动越快,死的也会越快
  • 更可靠 - 安全性和合规性要保障好
  • 可持续 - 输出不能时断时续,小步快跑才是正道,不要憋大招

从需求层面聚焦业务价值,效能团队的交付物是不是真正解决了用户的本质问题。比如:“女生减肥不是本质问题,女生爱美才是”。

大型企业具体是怎么做的

大型企业都有独立的团队负责:

  • 招行:挂在 PMO 下
  • 字节:独立部门
  • 腾讯:子通道
  • 华为:独立部门

毕竟对大型企业来说,提效是一个很大的杠杆。