Algorithm
本周选择的算法题是:Search Insert Position
规则如下:
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
Example 1:
Input: [1,3,5,6], 5
Output: 2
Example 2:
Input: [1,3,5,6], 2
Output: 1
Example 3:
Input: [1,3,5,6], 7
Output: 4
Example 4:
Input: [1,3,5,6], 0
Output: 0
Solution
我实现的方案:
Runtime:52 ms,快过 96.68%。
Memory:13.4 MB,低于 100%。
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
if len(nums) == 0: return 0
low, high = 0, len(nums) - 1
while low < high:
index = int((high + low) / 2)
if nums[index] == target:
return index
elif nums[index] > target:
high -= 1
else:
low += 1
return low if nums[low] >= target else low + 1
这是一道简单的二分查找题,用 left-most 方法即可。
优化的版本是这样:
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
low, high = 0, len(nums) - 1
while low <= high:
index = int((high + low) / 2)
if nums[index] == target:
return index
elif nums[index] > target:
high = index - 1
else:
low = index + 1
return low
减少了循环的次数,代码更加简洁。
Review
这是一篇如何利用碎片化读书的文章,对时间管理专家来说,每个人其实都有充足读书的时间,哪怕是自诩为喜欢读书的人,也会有一个月甚至一年没有读完一本书的情况出现,这就是这篇文章要说的事,现代社会拥有一长段连续时间是一个奢望,利用碎片化的时间反而成了最高效读书的方式。
这一篇和技术文章没有直接关系,但是和有没有时间多做技术储备有关系。
我从文章中结合自身总结了一些方法:
- 睡前时间阅读30分钟 - 有效,经常会阅读超过30分钟
- 通勤的时间 - 以前看极客时间经常要求自己抽出独立的时间,反而浪费了很多碎片化的时间
- kindle 是必备的
- 手边要有一本书 - 编译的时间或者等待什么的时候可以随手就能看
Tip
Swift 5.1 支持属性装饰器,在 Stop force unwrapping IBOutlets with @Delayed 一文中有很棒的妙用:
@propertyWrapper
struct Delayed<Value> {
private var _value: Value? = nil
var wrappedValue: Value {
get {
guard let value = _value else {
fatalError("Property accessed before being initialized.")
}
return value
}
set {
_value = newValue
}
}
}
这样就能避免强制拆包:
final class ThemeManager {
let theme: Theme
let colorScheme: ColorScheme
@Delayed private(set) var colors: ThemeColors // 避免了使用"!"强制拆包
init() {
theme = ...
colorScheme = ...
colors = theme.themeColors(for: colorScheme)
}
}
配合 @objc 还能用在 @IBOutlet 上。
Share
分享一些 iOS 下方向适配的策略。
影响方向的几个设置项:
- UIRequiresFullScreen
- modalPresentationStyle
- shouldAutorotate
- 设备方向锁
这些玩意儿在 iPad、iPhone 下表现不一样,列几个 Camera 下的场景来说明。
iPad
场景一
- 非全屏的 Camera
- 随设备方向旋转
Solution
- UIRequiresFullScreen - 忽略
- modalPresentationStyle - Non-fullscreen
- shouldAutorotate - 忽略
- 设备方向锁 - false
场景二
- 全屏的 Camera
- 随设备方向旋转
Solution
- UIRequiresFullScreen - false
- modalPresentationStyle - fullscreen
- shouldAutorotate - 忽略
- 设备方向锁 - false
场景三
- 全屏的 Camera
- 随设备方向旋转控制视图
Solution
- UIRequiresFullScreen - true
- modalPresentationStyle - fullscreen
- shouldAutorotate - true
- 设备方向锁 - false
要做到和系统的 Camera 体验一致,还需要防止黑边出现:
- 在
viewWillTransition
里动画设置视频方向 - 设置视图及根视图的
clipsToBounds
场景四
- 全屏的 Camera
- 随设备方向旋转控制视图
Solution
- UIRequiresFullScreen - true
- modalPresentationStyle - fullscreen
- shouldAutorotate - false
- 设备方向锁 - 忽略
配合 CMMotionManager
实现方向控制。
场景五
- 全屏的 Camera
- 随设备方向旋转
Solution
- UIRequiresFullScreen - false
- modalPresentationStyle - fullscreen
- shouldAutorotate - 忽略
- 设备方向锁 - false
通过 viewWillTransition
设置视频方向,其他控件由系统实现旋转。
iPhone
场景一
- 全屏的 Camera
- 随设备方向旋转控制视图
Solution
- UIRequiresFullScreen - 忽略
- modalPresentationStyle - fullscreen
- shouldAutorotate - 忽略
- 设备方向锁 - true
配合 CMMotionManager
实现方向控制。
场景二
- 全屏的 Camera
- 随设备方向旋转控制视图
Solution
- UIRequiresFullScreen - 忽略
- modalPresentationStyle - fullscreen
- shouldAutorotate - false
- 设备方向锁 - false
配合 CMMotionManager
实现方向控制。
场景二
- 全屏的 Camera
- 随设备方向旋转
Solution
- UIRequiresFullScreen - 忽略
- modalPresentationStyle - fullscreen
- shouldAutorotate - true
- 设备方向锁 - false
通过 viewWillTransition
设置视频方向,其他控件由系统实现旋转。
场景三
- 非全屏的 Camera
- 随设备方向旋转
Solution
- UIRequiresFullScreen - 忽略
- modalPresentationStyle - Non-fullscreen
- shouldAutorotate - 忽略
- 设备方向锁 - false
通过 viewWillTransition
设置视频方向,其他控件由系统实现旋转。