1. Algorithm: 每周至少做一个 LeetCode 的算法题
笔者的文章:
算法:找出存在子字符串的最先位置28. Implement strStr()
LeetCode 全集请参考:LeetCode Github 大全
# 题目
28. Implement strStr()
Implement strStr()
.
Return the index of the first occurrence of needle
in haystack
, or -1
if needle
is not part of haystack
.
Clarification:
What should we return when needle is an empty string? This is a great question to ask during an interview.
For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf().
Example 1:
Input: haystack = "hello", needle = "ll"
Output: 2
复制代码
Example 2:
Input: haystack = "aaaaa", needle = "bba"
Output: -1
复制代码
Example 3:
Input: haystack = "", needle = ""
Output: 0
复制代码
Constraints:
0 <= haystack.length, needle.length <= 5 * 104
haystack and needle consist of only lower-case English characters.
复制代码
1. 穷举解法
两个 for 循环匹配即可,这里容易遗漏的点是判断 needle 是否为空字符串""
, 是的话返回 0.
class Solution {
public int strStr(String haystack, String needle) {
// check null
if (haystack == null && needle == null) {
return 0;
}
if (haystack == null || needle == null) {
return -1;
}
int hlen = haystack.length();
int nlen = needle.length();
// check ""
if (nlen == 0) {
return 0;
}
for(int i = 0; i <= hlen - nlen; i++) {
for(int k = 0; k < nlen; k++) {
if (haystack.charAt(i + k) != needle.charAt(k)) {
break;
}
if (k == nlen - 1) {
return i;
}
}
}
return -1;
}
}
复制代码
2. 优雅的写法
假设两个字符串都不为空,可以用下面优雅的写法。
class Solution {
public int strStr(String haystack, String needle) {
for (int i = 0; ; i++) {
for (int k = 0; ; k++) {
if (k == needle.length()) return i;
if (i + k == haystack.length()) return -1;
if (haystack.charAt(i + k) != needle.charAt(k)) break;
}
}
}
}
复制代码
2. Review: 阅读并点评至少一篇英文技术文章
笔者的文章:
翻译:5分钟介绍AI人工智能,机器学习和深度学习
术语“人工智能”已经浮动了一段时间。我们在科幻电影,我们与之对抗的“ AI”游戏机器人,谷歌搜索以及哦,是的,那些有一天要占领世界的机器人中看到了这一点。但是,“机器学习”和“深度学习”已经浮出水面,许多人都问它们到底是什么。
人工智能
人工智能是通用的类别,对这三个类别都是通用的。在图中,人工智能将是包含机器学习和深度学习的更大的封装圈子。人工智能基本上是机器所展示的任何智能,它可以针对某个问题将其引导至最优或次优解决方案。最简单的 AI 示例可以以 Tic-Tac-Toe(井字棋) AI 播放器的形式找到。如果机器人遵循以下预编程算法,则它将永远不会输掉游戏:(由 Wikipedia 提供)
1.如果某人受到“威胁”(即连续两次),则取剩余的正方形。
2.如果某举动“分叉”一次造成两个威胁,则进行该举动。否则,
3.如果中心广场是免费的,则采取。否则,
4.如果您的对手在角落里玩,则走到对面的角落。否则,
5.如果有一个空的角落。否则,
6.取任何空的正方形。
现在,像这样的算法不具备大多数人将“ AI”与之相关的认知,学习或解决问题的能力。然而,算法只是给定问题及其状态的最优解决方案的代理。
维基百科为人工智能代理提供了另一个定义:
任何能够感知其环境并采取行动以最大程度地成功实现其目标的设备
属于 AI 但不属于机器学习的代理通常是仅将决策树用于逻辑的代理,或者是使用规则和指令构建的代理。
最受欢迎的 3 种 Ai 文章:
1.使用Tensorflow实施RNN-LSTM的新手指南
Keras备忘单:Python中的神经网络
3.制作简单的神经网络
机器学习:认知的迹象
亚瑟·塞缪尔(Arthur Samuel)在 1959 年创造了“机器学习”一词,将其定义为“无需明确编程即可学习的能力”。机器学习最基本的形式是一种使用算法来解析数据,从中学习并随后对世界上的事物进行确定或预测的实践。对于初学者来说,最常见的例子是房价。像 Redfin 或 Zillow 这样的网站如何预测目前拥有房屋的价格?
没那么复杂。机器学习的本质是,实际上在很多方面都做得最好。房屋价格预测模型会查看大量数据,每个数据点都具有多个维度,例如大小,卧室数量,浴室数量,院子空间等。它会根据这些输入参数创建一个函数,然后将系数移动到这些参数中的每一个都可以查看越来越多的数据。
这种机器学习方法称为“监督学习”,其中提供给模型的数据包括每个输入集的问题答案。它基本上提供了输入参数(称为要素)以及每组要素的输出,模型从中调整其功能以匹配数据。然后,当给出任何其他输入数据时,模型可以执行相同的功能并提供准确的输出。
机器学习的其他派系是无监督学习和强化学习。简而言之,无监督学习只是在数据中找到相似之处-在我们的房屋示例中,该数据将不包含房价(该数据仅是输入,而没有输出),并且该模型可以说“嗯,基于在这些参数上,房屋 1 最类似于房屋 3”或类似的房屋,但无法预测给定房屋的价格。
最好使用简单,简短的图表来解释强化学习:
代理在环境中执行操作,该操作被解释为奖励和状态表示,这些操作将反馈给代理。想想一个小宝宝:哭泣会产生糖果,这是回报。随着时间的流逝,如果父母继续满足孩子对糖果的渴望,那么婴儿每次想要糖果时都会学会哭泣。
深度学习:与人类的联系
深度学习的灵感来自大脑的结构和功能,即许多神经元的相互连接。神经网络是模仿大脑生物结构的算法。
从麻省理工学院新闻:
在人脑上松散地建模,神经网络由成千上万甚至数百万个紧密互连的简单处理节点组成。当今的大多数神经网络都组织成节点层,它们是“前馈”的,这意味着数据仅在一个方向上通过它们。单个节点可能连接到其下一层的多个节点(从该节点接收数据),以及它上一层的多个节点(该节点向其发送数据)。<br>
节点将为其每个传入连接分配一个数字,称为“权重”。当网络处于活动状态时,该节点通过其每个连接接收不同的数据项-不同的编号,并将其乘以关联的权重。然后,将得到的乘积加在一起,得到一个数字。如果该数字低于阈值,则该节点不会将任何数据传递到下一层。如果数字超过阈值,则节点“触发”,这在当今的神经网络中通常意味着沿其所有传出连接发送数字(加权输入的总和)。<br>
在训练神经网络时,其所有权重和阈值最初都设置为随机值。训练数据被馈送到底层(输入层),并经过后续层,以复杂的方式被相乘并相加,直到最终到达输出层,并进行了彻底的转换。在训练过程中,将不断调整权重和阈值,直到带有相同标签的训练数据始终产生相似的输出为止。
深度学习基本上是对类固醇的机器学习。处理要素有多层,通常,每一层都提取一些有价值的信息。例如,一个神经网络可以处理用于驾驶自动驾驶汽车的图像。每个图层都会处理不同的内容,例如,第一个图层可能是检测道路两侧的边缘。另一层可能正在检测图像中的车道线,而另一层可能是其他车。
那是很多信息打包成的单词。NVDIA 的图像提供了极为紧凑的可视化效果:
不管这些差异如何,这三个因素在今天都将继续对我们的世界产生深远的影响,有一天,有可能将我们带入一个机器人社会。
参考
https://becominghuman.ai/ai-machine-learning-deep-learning-explained-in-5-minutes-b88b6ee65846
3. Tips: 学习至少一个技术技巧
笔者的文章:
Swift 5 用TableView实现动态Excel表格Spreadsheet
动态 Excel 表格
实现的功能样子如下:
数据由二维数组驱动model = [[String]]
行数由有model.count
决定
每一列间隔相等,column 列数由数据个数决定model[0].count
。
实现方案分析
在 google 上搜索 Spreadsheet 有很多强大的表格。
考虑到简单实现,笔者用 UITableview 来实现,每一行都是一个 UIStackView, 边框用 UIView 来实现。
SpreadSheetView
复用的 tableView
//
// SpreadSheetView.swift
// SpreadsheetView
//
// Created by zgpeace on 2021/3/7.
//
import UIKit
class SpreadSheetView: UIView {
private lazy var tableView: UITableView = {
let tableView = UITableView(frame: .zero)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.separatorStyle = .none
tableView.delegate = self
tableView.dataSource = self
return tableView
}()
private let viewModel: [[String]]
public init(viewModel: [[String]]) {
if viewModel.count < 1 {
fatalError("less than one row")
}
self.viewModel = viewModel
super.init(frame: .zero)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
addSubview(self.tableView)
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: topAnchor, constant: 50),
tableView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -50),
tableView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
tableView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12)
])
tableView.register(SpreadsheetCell.self, forCellReuseIdentifier: "\(SpreadsheetCell.self)")
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableView.automaticDimension
}
}
extension SpreadSheetView: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
viewModel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "\(SpreadsheetCell.self)", for: indexPath) as? SpreadsheetCell else {
return UITableViewCell()
}
let model = SpreadsheetItemViewModel(
items: viewModel[indexPath.row],
isFirstLine: indexPath.row == 0,
isLastLine: indexPath.row == viewModel.count - 1)
cell.update(viewModel: model)
return cell
}
}
extension SpreadSheetView: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
}
}
复制代码
SpreadsheetItemViewModel
SpreadsheetItemViewModel
每一行的一维数组,
判断是否为第一列(标题加背景色,加粗等),
是否为最后一列(要加上最下面的边)
BorderViews, 存着上下左右四个分割线,默认每个表格显示 Top,Left 边线,每一行的最后一个增加 Right 的线;最后行增加 Bottom 的线。
//
// SpreadsheetItemViewModel.swift
// SpreadsheetView
//
// Created by zgpeace on 2021/3/7.
//
import Foundation
import UIKit
struct SpreadsheetItemViewModel {
let items: [String]
let isFirstLine: Bool
let isLastLine: Bool
}
struct BorderViews {
let topBorder: UIView
let bottomBorder: UIView
let leftBorder: UIView
let rightBorder: UIView
}
复制代码
SpreadsheetCell
tableViewCell 的复写,主要是用 StackView 实现相等的空格大小
//
// SpreadsheetCell.swift
// SpreadsheetView
//
// Created by zgpeace on 2021/3/7.
//
import UIKit
class SpreadsheetCell: UITableViewCell {
// private var itemView: UIView!
private var borderViewArray: [BorderViews?] = []
private var labelArray: [UILabel?] = []
private var labelContentViewArray: [UIView?] = []
private lazy var mainStackView: UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.distribution = .fillEqually
stack.alignment = .top
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
private var viewModel: SpreadsheetItemViewModel!
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
public func update(viewModel: SpreadsheetItemViewModel) {
self.viewModel = viewModel
if !mainStackView.isDescendant(of: self) {
setupView()
}
applyViewModel()
layoutIfNeeded()
}
func applyViewModel() {
let lastIndex = viewModel.items.capacity - 1
for (index, item) in viewModel.items.enumerated() {
labelArray[index]?.text = item
labelArray[index]?.sizeToFit()
hideUIViewBorder(withIsLastLine: viewModel.isLastLine,
isLastIndex: index == lastIndex,
bottomBorder: borderViewArray[index]?.bottomBorder ?? UIView(),
rightBorder: borderViewArray[index]?.rightBorder ?? UIView())
}
}
func setupView() {
addSubview(mainStackView)
for item in viewModel.items {
let label = buildLabel(with: item)
let view = buildLabelView(with: label)
let topBorder = view.addBorder(.top, color: .darkGray, thickness: 1)
let bottomBorder = view.addBorder(.bottom, color: .darkGray, thickness: 1)
let leftBorder = view.addBorder(.left, color: .darkGray, thickness: 1)
let rightBorder = view.addBorder(.right, color: .darkGray, thickness: 1)
mainStackView.addArrangedSubview(view)
borderViewArray.append(BorderViews(topBorder: topBorder, bottomBorder: bottomBorder, leftBorder: leftBorder, rightBorder: rightBorder))
labelArray.append(label)
labelContentViewArray.append(view)
NSLayoutConstraint.activate([
view.topAnchor.constraint(equalTo: mainStackView.topAnchor),
view.bottomAnchor.constraint(equalTo: mainStackView.bottomAnchor)
])
}
NSLayoutConstraint.activate([
mainStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
mainStackView.trailingAnchor.constraint(equalTo: trailingAnchor),
mainStackView.topAnchor.constraint(equalTo: topAnchor),
mainStackView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
private func hideUIViewBorder(
withIsLastLine isLastLine: Bool,
isLastIndex: Bool,
bottomBorder: UIView,
rightBorder: UIView) {
bottomBorder.isHidden = !isLastLine
rightBorder.isHidden = !isLastIndex
}
private func buildLabel(with text: String) -> UILabel {
let label = UILabel()
label.text = text
label.numberOfLines = 0
label.textAlignment = .left
label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
label.setContentCompressionResistancePriority(.required, for: .horizontal)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}
private func buildLabelView(with label: UILabel) -> UIView {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
label.topAnchor.constraint(equalTo: view.topAnchor, constant: 8),
label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8)
])
return view
}
}
复制代码
画边线 UIView+Border
//
// UIView+Border.swift
// SpreadsheetView
//
// Created by zgpeace on 2021/3/7.
//
import Foundation
import UIKit
extension UIView {
func addBorder(_ edge: UIRectEdge, color: UIColor, thickness: CGFloat) -> UIView {
let subview = UIView()
subview.translatesAutoresizingMaskIntoConstraints = false
subview.backgroundColor = color
addSubview(subview)
switch edge {
case .top, .bottom:
subview.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
subview.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
subview.heightAnchor.constraint(equalToConstant: thickness).isActive = true
if edge == .top {
subview.topAnchor.constraint(equalTo: topAnchor).isActive = true
} else {
subview.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
case .left, .right:
subview.topAnchor.constraint(equalTo: topAnchor).isActive = true
subview.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
subview.widthAnchor.constraint(equalToConstant: thickness).isActive = true
if edge == .left {
subview.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
} else {
subview.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
}
default:
break
}
return subview
}
}
复制代码
例子演示 ViewController
//
// ViewController.swift
// SpreadsheetView
//
// Created by zgpeace on 2021/3/4.
//
import UIKit
class ViewController: UIViewController {
private lazy var spreadsheetView: SpreadSheetView = {
let viewModel: [[String]] = [
["index", "name", "hobby"],
["1", "John", "Reading"],
["2", "Lee", "Play Guitar"]
]
let view = SpreadSheetView(viewModel: viewModel)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var spreadsheetView1: SpreadSheetView = {
let viewModel: [[String]] = [
["index", "name", "hobby", "quotes\ndetail"],
["1", "John", "Reading", "The fool doth think he is wise, but the wise man knows himself to be a fool."],
["2", "Lee", "Play Guitar", "Love all, trust a few, do wrong to none."],
["3", "Elsa", "Create ice", "Be not afraid of greatness. ..."]
]
let view = SpreadSheetView(viewModel: viewModel)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(spreadsheetView)
view.addSubview(spreadsheetView1)
NSLayoutConstraint.activate([
spreadsheetView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16),
spreadsheetView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16),
spreadsheetView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 16),
spreadsheetView.heightAnchor.constraint(equalToConstant: 250.0),
spreadsheetView1.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16),
spreadsheetView1.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16),
spreadsheetView1.topAnchor.constraint(equalTo: spreadsheetView.bottomAnchor, constant: 16),
spreadsheetView1.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
])
}
}
复制代码
代码下载
https://github.com/zgpeace/SpreadsheetView
其它实现
https://github.com/bannzai/SpreadsheetView
https://www.youtube.com/watch?v=l8VxogiHCY8&ab_channel=iOSAcademy
4. Share: 分享一篇有观点和思考的技术文章
笔者的文章:
极客大学产品经理训练营:PRD 产品原型文档框架 第11课总结
讲师:邱岳
1. PRD 产品原型文档的各种元素
PRD: Product Requirement Document 产品原型文档
基本元素(目录、标题、作者、版本、历史等)。
场景描述。
需求背景、现状、问题、目标。
奶粉添加三聚氰胺就是目标错误的结果。国家质检牛奶高蛋白的度量是氮元素,所以厂家就添加含氮元素量比较大的作料,比如三聚氰胺。用户真正的诉求是高蛋白,高营养的奶粉。
1.1 其它元素
☞ FURPS+: 功能性(Functional)、可用性(Usability)
☞ 可靠性(Reliability)、性能(Performance)、可支持性(Supportability)。
2. PRD 是什么
What --> How --> Why
2.1 PRD 需要如何推进
Why --> How --> What
2.2 PRD 组织方式
以用例为纲;
以特性为纲;
以页面(模块)为纲
以场景 / 故事为纲
文档的基本要素
交代清楚背景和目的(Starts from why)
描述用户场景和用户角色,以及用户问题(用什么方法解决谁的什么问题)
提纲挈领地粗略给出系统的大图
用例图
页面架构图
概念模型图
主要页面 / 模块
核心流程 / 状态
以用例为【目录】逐步发展
每个用例中包含流程,涉及到相关界面、流程图、状态图、商业规则时,包含进来。
可以将【界面】、【流程图】、【商业规则】单独再组织索引一遍。
列出非功能性需求。
可行性评估、资源评估、计划评估、第三方支持、风险评估等。
竞品分析市场分析。
2.3 组装 PRD 几个建议
评论