CodingTour
ARTS #188 | 新年快乐

Algorithm

本周选择的算法题是:Subarray Sums Divisible by K

规则

Given an integer array nums and an integer k, return the number of non-empty subarrays that have a sum divisible by k.

A subarray is a contiguous part of an array.

Example 1:

Input: nums = [4,5,0,-2,-3,1], k = 5
Output: 7
Explanation: There are 7 subarrays with a sum divisible by k = 5:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]

Example 2:

Input: nums = [5], k = 9
Output: 0

Constraints:

  • 1 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • 2 <= k <= 104

Solution

impl Solution {
    pub fn subarrays_div_by_k(nums: Vec<i32>, k: i32) -> i32 {
        let mut ans = 0;
        let mut modGroups = vec![0; k as usize];
        modGroups[0] = 1;
        let mut prefixMod = 0;

        for num in nums {
            prefixMod = (prefixMod + num % k + k) % k;

            ans += modGroups[prefixMod as usize];
            modGroups[prefixMod as usize] += 1;
        }
        
        ans
    }
}

Review

Here are my “lessons learned” after 5+ years of DevOps consulting

作者在这篇文章里分享了诸多经验,标题中的关键词有两个:DevOps、consulting,本文着重介绍的是交付、客户和沟通、协作。

介绍其中三个 tips:

  • 文档写作要尽可能早和快。早是为了减少风险,快是为了真的完成它。作者的工作是顾问,顾问难以避免与人打交道,而文档是连接 people 和 processes 的工具之一,想让文档发挥作用,最基本的是不要试图同时写和编辑,大概率会陷入完美主义的陷阱中。有意思的是,很多知名作家在采访时也表达过类似的观点,通常手稿和前几版要一气呵成,尽量避免边写作边修改,因为那样可能永远也完不成一件作品
  • 尽早通过基础设施即代码和发布流水线完成一次 release。“大爆炸” 理论也适用于软件交付。一次巨大的爆炸可能产生新的宇宙,生产部署也可能是这样的,每次基础设施和代码的大规模部署,要么是混乱的结果,要么(运气好)是一个可工作的应用程序,如今很多公司仍旧是在项目 “完成” 的最后一天才发布到生产,这种行为像极了在最后一刻期望通过 hope and pray 获得 “大爆炸” 的眷顾
  • 让和客户参与设计,共同创作。You can’t hide。顾问面向的是 B 端客户,因此需要一些必要的软技能完成 “最难的事” — 和客户一起工作、帮助客户拿到结果、赢得客户的信任。Re-adjust your pace to match the client’s pace,可以翻译为 “与客户同频”,没有所谓的快与慢、好与差,这些都是相对的,能站在客户角度讲清楚风险和收益比 “最佳实践” 更重要

作者文笔不错,总而言之是很不错的文章。

Tip

用于测试 Apple Push 的小工具:Knuff,Apple 证书设置起来比较麻烦,加上国内往往会借助三方平台(如极光)作为推送中间件,过程中遇到问题不好排查是证书导致的还是配置不正确,此时用 Knuff 可以方便排查。

Share

分享几个 Python f-strings 的妙用~

f-strings 一般被用来格式化字符串,比如原本的:

name = "Musk"
age = 52
print("Hello, %s. You are %s." % (name, age))
# Hello Musk. You are 52.

用 f-strings 只需要:

name = "Musk"
age = 52
print(f"Hello, {name}. You are {age}.")
# Hello Musk. You are 52.

是一个让工作和生活变得更轻松的好工具,不过 f-strings 的功能远不只如此。

日期和时间格式化

日期转为字符串不用显式通过 strftime 完成:

import datetime
today = datetime.datetime.today()
print(f"{today:%Y-%m-%d}")
# 2023-01-17
print(f"{today:%Y}")
# 2023

具体语法参见: strftime - format date and time

变量名和调试

x = 10
print(f"x = {x}")
print(f"{x = :}") # 两者等价
print(f"{x = :.3f}") # 可以添加修饰符

字符串表示

打印一个类时,默认是调用 __str__ 方法,如果想调用 __repr__ 只需要加上 !r 就好:

class User:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

    def __repr__(self):
        return f"User's name is: {self.first_name} {self.last_name}"

user = User("Elon", "Musk")
print(f"{user}")
# Elon Musk
print(f"{user!r}")
# User's name is: Elon Musk

完全支持格式化规范

f-strings 支持 Format Specification Mini-Language,所以你可以用很多修饰符:

text = "hello world"

# Center text:
print(f"{text:^15}")
# '  hello world  '

number = 1234567890
# Set separator
print(f"{number:,}")
# 1,234,567,890

number = 123
# Add leading zeros
print(f"{number:08}")
# 00000123

除了格式化数字、日期外,对齐、居中、添加前导零、空格等等,其他格式化方案支持的 f-strings 同样也支持。

可嵌套

number = 254.3463
print(f"{f'${number:.3f}':>10s}")
# '  $254.346'

变量也支持:

import decimal
width = 8
precision = 3
value = decimal.Decimal("42.12345")
print(f"output: {value:{width}.{precision}}")
# 'output:     42.1'

条件格式化

f-strings 支持三元运算符:

x = 10
print(f"{x if x > 5 else '1'}")
# 10

Lambda

print(f"{(lambda x: x**2)(3)}")
# 9

结束语

正如你看到的,f-strings 具有比大多数人想象不到的更多功能,其实这些功能在 Python 的文档里都有提及,参见: PEP 498 – Literal String Interpolation,因此我们不仅要阅读 f-strings,也建议阅读可能使用的任何其他 Python 模块/特性的文档,深入研究文档通常会发现一些即使在 StackOverflow 中也找不到的非常有用的功能,而且 f-strings 实际上是 Python 所有格式化方案中最快的,即时你喜欢用老派的方法,也可以考虑为了提高性能切换到 f-strings。

ps: 不建议在 f-strings 中使用太多 lambda、条件格式化和嵌套,虽然它支持,但无疑会降低代码的可读性。