
Creational Patterns
- Factory Pattern
- Singleton Pattern
- Builder Pattern
Structural Patterns
- Adapter Pattern
- Composite Pattern
- Decorator Pattern
- Proxy Pattern
Behavioral Patterns
- Strategy Pattern
- Observer Pattern
- Command Pattern
Creational Patterns
Structural Patterns
Behavioral Patterns
// TODO: –
// TODO: – 分享Flutter集成经验
// TODO: – 详细讲解Runtime原理和在项目中的应用案例
词根词缀预习表
词根/词缀 | 含义 | 例词及释义 |
---|---|---|
act | 做 | exact adj. 精确的;准确的 |
reg | 国王 | regent n. 摄政者 |
philo | 爱 | philosophy n. 哲学;哲理 |
chron | 时间 | chronic adj. (疾病) 慢性的 |
vari | 变化 | variety n. 品种;变化 |
equi | 相等 | equity n. 公平,公正 |
cav | 洞 | excavate v. 挖掘,开凿 |
mut | 改变 | mutual adj. 相互的;共同的 |
pan | 面包 | companion n. 共事者;同伴 |
vas | 走 | invasion n. 入侵,侵略 |
给定一个字符串 s
,请你找出其中不含有重复字符的 最长
子串
的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成滑动窗口
的思路
class Solution {
func lengthOfLongestSubstring(_ s: String) -> Int {
var charMap: [Character: Int] = [:]
var start = 0
var maxLength = 0
let count = s.count
for i in 0..<count {
// 1、取出当前字符
let char = s[s.index(s.startIndex, offsetBy: i)]
// 2、如果这个字符已经在字典里,取出他上次的位置,更新起点为上次出现的位置的后面
if let lastIndex = charMap[char], start <= lastIndex {
start = lastIndex + 1
}
// 3、更新到字典里
charMap[char] = i
// 4、计算新的长度为当前index-起点,并更新长度
maxLength = max(maxLength, i - start + 1)
}
return maxLength
}
}
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0] 输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] 输出:[8,9,9,9,0,0,0,1]
提示:
[1, 100]
内0 <= Node.val <= 9
/**
* Definition for singly-linked list.
* public class ListNode {
* public var val: Int
* public var next: ListNode?
* public init() { self.val = 0; self.next = nil; }
* public init(_ val: Int) { self.val = val; self.next = nil; }
* public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
* }
*/
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
/*
哑:哑节点开头,哑节点固定,结果返回哑节点的后继
标:标识两个遍历的节点和一个生成的新节点
移:while循环向前走
进:无法移动后再处理进位
*/
let dummyHead = ListNode()
var currentNode = dummyHead
var carry = 0
var p = l1
var q = l2
while p != nil || q != nil {
/*
只要不是都走到尽头,都要进入这里
*/
let pValue = p?.val ?? 0
let qValue = q?.val ?? 0
var sum = pValue + qValue + carry
// 1、是否要进位
carry = sum / 10
// 2、新节点的后继(value为当前相加取余)
currentNode.next = ListNode(sum % 10)
// 3、往后移动
currentNode = currentNode.next!
p = p?.next
q = q?.next
}
/*
两个单链表都走到尽头了,如果存在进位,要追加一个后继
这个节点的value只能是1,实际是最高位
*/
if carry > 0 {
currentNode.next = ListNode(carry)
}
return dummyHead.next
}
}
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
/*
从头开始遍历,看剩下的数里是否有相加等于目标数
时间复杂度: O(n2)
优化:
遍历一次数组,生成一个字典[int: int],
valueForKey来找index
*/
let count = nums.count
if count == 0 {
return []
}
for index in 0..<count {
let currentValue = nums[index]
for targetIndex in 0..<count {
if index == targetIndex {
continue
}
let targetValue = nums[targetIndex]
if currentValue + targetValue == target {
return [index, targetIndex]
}
}
}
return []
}
}
extension Notification {
public var keyboardSize: CGSize? {
return (userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size
}
public var keyboardAnimationDuration: TimeInterval? {
return userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval
}
}
public protocol KeyboardObserving: AnyObject {
func startObservingKeyboard()
func stopObservingKeyboard()
func keyboardWillShow(notification: Notification)
func keyboardWillHide(notification: Notification)
}
UIViewController有生命周期,需要在特定的阶段开启或取消对通知的监听,在willAppear
和willDisappear
阶段调用func startObservingKeyboard()
及func stopObservingKeyboard()
是比较方便的。尤其是present出另一个viewController的情况下,如果没有取消对键盘的监听,那么第二个ViewController触发键盘可能会影响第一个控制器执行升起键盘后的动画。
这个协议希望被需要监听键盘即将升降的对象来遵守,通常是UIViewController
,所以我们在默认实现中也通过where Self: UIViewController
限制为UIViewController
。
public extension KeyboardObserving where Self: UIViewController {
func startObservingKeyboard() {
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { [weak self] (notification) in
self?.keyboardWillShow(notification: notification)
}
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { [weak self] (notification) in
self?.keyboardWillHide(notification: notification)
}
}
func stopObservingKeyboard() {
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
}
class MediaBrowseViewController: UIViewController, KeyboardObserving {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// 在生命周期的即将显示阶段 调用协议中的开启监听方法的默认实现
self.startObservingKeyboard()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// 在生命周期的即将消失阶段 调用协议中的结束监听方法的默认实现
self.stopObservingKeyboard()
}
// MARK: - KeyboardObserving
func keyboardWillShow(notification: Notification) {
self.replyInputView.showMaskIfPossible()
if let height = notification.keyboardSize?.height, let duration = notification.keyboardAnimationDuration {
// 这里执行键盘即将升起时UI变化的任务
UIView.animate(withDuration: duration) {
self.replyInputView.willAscend()
self.replyInputView.snp.updateConstraints { make in
make.bottom.equalToSuperview().offset(-height)
}
self.view.layoutSubviews()
}
}
}
func keyboardWillHide(notification: Notification) {
if let duration = notification.keyboardAnimationDuration {
// 这里执行键盘即将降下时UI变化的任务
UIView.animate(withDuration: duration) {
self.replyInputView.willDescend()
self.replyInputView.snp.updateConstraints { make in
make.bottom.equalToSuperview().offset(-tabbarHeight)
}
self.view.layoutIfNeeded()
}
}
}
}