Algorithm
本周选择的算法题是:Insert Interval
规则如下:
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1:
Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
Output: [[1,5],[6,9]]
Example 2:
Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
Output: [[1,2],[3,10],[12,16]]
Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].
Example 3:
Input: intervals = [], newInterval = [5,7]
Output: [[5,7]]
Example 4:
Input: intervals = [[1,5]], newInterval = [2,3]
Output: [[1,5]]
Example 5:
Input: intervals = [[1,5]], newInterval = [2,7]
Output: [[1,7]]
Constraints:
0 <= intervals.length <= 104
intervals[i].length == 2
0 <= intervals[i][0] <= intervals[i][1] <= 105
intervals
is sorted byintervals[i][0]
in ascending order.newInterval.length == 2
0 <= newInterval[0] <= newInterval[1] <= 105
Solution
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
ans, index, n = [], 0, len(intervals)
while index < n and intervals[index][1] < newInterval[0]:
ans.append(intervals[index])
index += 1
ans.append(newInterval)
while index < n:
if intervals[index][0] <= ans[-1][1]:
ans[-1][0] = min(ans[-1][0], intervals[index][0])
ans[-1][1] = max(ans[-1][1], intervals[index][1])
else:
ans.append(intervals[index])
index += 1
return ans
Review
The Inside Story on New-Style Classes
Python 语言的设计者 Guido van Rossum 早些年在 2.x 上的一些思考。
我感兴趣的主要有其中三部分:
- descriptor - 一个基于 POP 语言的 OOP 设计实现,Objective-C 里也有一套类似的机制
- slots - 与传统
__dict__
相比,slots 在性能和内存使用率上有更多的优势,其基于数组,支持内存随机访问。而且由于 slots 可以和__dict__
在同一个类中共存,所以可以认为是一种优化 - MRO - Python 的多重继承实现
Tip
在 lldb 中可以直接通过锁自身查看是哪个线程获取了该锁。
以 NSLock
为例,假设它的内存地址为 0x00006000002c79c0:
(lldb) x/16 0x00006000002c79c0
0x6000002c79c0: 0x86cf8b50 0x00007fff 0x00000000 0x00000000
0x6000002c79d0: 0x4d55545a 0x00000000 0x00000000 0x000020a0
0x6000002c79e0: 0x00000000 0x4d55545a 0x00068c91 0x00000000
0x6000002c79f0: 0x00000002 0x00000000 0xffffffff 0xffffffff
查看它偏移量为 0x28 的位置:
(lldb) p (char*)0x6000002c79c0 + 0x28
(char *) $8 = 0x00006000002c79e8 "\xffffff91\xffffff8c\x06"
0x28 = 0x10 + 0x18
将它的值转为十进制整型:
(lldb) p *((int *)0x00006000002c79e8)
(int) $9 = 429201
查看线程列表:
(lldb) thread list
* thread #1: tid = 0x68c91, 0x000000010670717a VideoStudio`-[PVResourceDemoVC viewDidLoad](self=0x00007fb5f4734f00, _cmd="viewDidLoad") at PVResourceDemoVC.m:49:28, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
thread #2: tid = 0x68d44, 0x00007fff5dca14ce libsystem_kernel.dylib`__workq_kernreturn + 10
thread #3: tid = 0x68d49, 0x00007fff2018f728 libobjc.A.dylib`objc_release + 8
thread #5: tid = 0x68d88, 0x00007fff5dc9fdfa libsystem_kernel.dylib`mach_msg_trap + 10, name = 'com.apple.uikit.eventfetch-thread'
thread #7: tid = 0x68d8a, 0x00007fff5dca14ce libsystem_kernel.dylib`__workq_kernreturn + 10
thread #1 的 tid 为 0x68c91,正好是十进制 429201:
(lldb) p 0x68c91
(int) $10 = 429201
表示 lock 当前是由 thread #1 占有。
Share
CI
早前为了解决 Android 构建机器环境部署困难的问题,我们引入了 Docker,因为构建环境都是基于 Linux 的,所以将环境整体打包成 Docker 镜像可以比较完美的解决我们的问题。
但是 iOS 的构建必须基于 macOS 完成,而 macOS 不能在 Linux 环境内通过 Docker 镜像运行(就算能运行,各种驱动不兼容也会造成性能低下、维护困难等问题)。
不过好在 macOS 提供了自己的虚拟化框架 Hypervisor.framework,市面上也有基于它的商业化解决方案:
- Docker Desktop
- VMWare Fusion
考虑到 VMWare Fusion 底层也是基于 Hypervisor.framework,我们就以此开发了基于 macOS 的虚拟化构建方案:
- 制作一个 macOS 的虚拟机环境
- 配置环境和必要的缓存
- 自动登录
- launchd 启动后自动执行脚本
最终它也可以像 Docker 那样,在终端通过 vmrun
完成对“容器“的操作,如克隆、启动和结束等:
# 启动
vmrun start path/to/vmwarevm nogui
# 结束
vmrun stop /path/to/vmx
# 克隆
vmrun clone /path/to/source/vmx /path/to/target/vmx full -cloneName=NewName