diff --git a/hexo.swift/Output/about/index.html b/hexo.swift/Output/about/index.html new file mode 100644 index 0000000..ee8f7aa --- /dev/null +++ b/hexo.swift/Output/about/index.html @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

about

\ No newline at end of file diff --git "a/hexo.swift/Output/blogs/2019Q3\346\212\245\345\221\212/index.html" "b/hexo.swift/Output/blogs/2019Q3\346\212\245\345\221\212/index.html" new file mode 100644 index 0000000..2f8a6ae --- /dev/null +++ "b/hexo.swift/Output/blogs/2019Q3\346\212\245\345\221\212/index.html" @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

2019Q3报告

发布于 2019-10-01

2019 Q3 报告

工作(实习情况)

整个 Q3 几乎都在依图实习,但是说实话算不上是一段很好的实习体验,首先他 10106,相比去年暑假实习的9116,我感觉更累了一点,可能是因为中间穿插了很多秋招面试和复习。

在这三个月里,自认为的提升:

  • 前端(React):5%
  • 后端(Java + Spring Cloud):20%
  • Docker:80%

说说我这三个月做了什么,我参与的项目是给测试部门内部使用的一个性能测试平台,可以并发的对被测服务发起压力。

我主要的工作是:

  • 参与2.5个版本的前端迭代
  • 后端时序图取点算法和 Web 协议配置的内部接口
  • 所有版本的部署架构,从单机 docker-compose 到双机 k8s 尝试再到双机 Docker Swarm,部署灵活性增加50%左右

总结下来:在前端方面几乎没有提升,只是在做一些复杂的 UI 和逻辑处理;后端方面了解了部分的 Java编程规范,对面向对象和设计模式有了进一步了解;在 Docker 方面应该算是学到最多的,但也仅限于 Dockerfile 和 yml 的编写,突然就想起了去年实习的时候和秋哥说想学 Docker,秋哥说把公司的弄懂就会了,不用刻意去学,还是很中肯的。

Side Projects

番茄计

在实习的第一个月,忘了出于什么原因,每天都会写这个 App,可能只是之前的一个 idea 想着要去实现它,看看收费带来的用户数如何。

这个 App 的初衷是为了统计我做各个项目花了多少时间,来源是图拉鼎的那个自己的项目,后来写着写着变成了一个番茄钟应用,我认为的创新之处在于将它和 Apple 的待办事项结合起来,不用再为我这个单独的 App 去创建 todo(当然也是可以的)

这个 App 我接入了 Fabric,可以实时看到用户数,不过看数据似乎并不怎么样,但我依然会继续 focus 在这个项目上,但不会再仅仅是做需求,我会借此熟悉 UIKit 的一些 API 和深入 iOS 特性。

Vapor 博客

因为 SwiftUI 的推出,又有开发者做了像 SwiftWebUI 这样的第三方库,看到了使用 Swift 完成前后端开发的希望,一开始的尝试是使用 Vapor 提供的基础组件自己写一套后端框架,但是有点难,暂时搁置,选择用 Vapor 搭一套后端框架,前端暂时使用 Vapor 官方推荐的 Leaf 模版,之后等 SwiftUI 成熟一些打算换成 SwiftWebUI 这样的前端选择。

目前实现的功能只有博客的增删改查,不过也尝试了 TDD 的开发方式,写了增删改查的 UT,每次看见 UT 全过还是很兴奋的。

秋招情况

秋招算是比较惨烈了,当然除了AT,我其他投的基本上都是不用996的公司,目前的秋招结果如下

  • 腾讯,被一个不知道什么部门和WXG共发起4轮一面,皆挂
  • 阿里,一面挂
  • 字节,简历挂
  • 美团,三轮技术面一轮HR面,意向书
  • 英语流利说,两轮技术面已过,hr说等hr面
  • airbnb,笔试两道题只a了一道,凉凉
  • 微软,石沉大海
  • xmind,石沉大海
  • ……

为何选择秋招而不转正

本来没打算秋招,依图的部门 leader 也很早就跟我说了转正的事情,但是让我最想继续参加秋招的理由是:WWDC Scholarship,我想如果不参加秋招,这个荣誉之后也很难再用上了吧;另一方面,以前觉得全栈,好厉害啊,但是我似乎对于全栈有一些误解。以前认为全栈可能就是能够独立完成一个前后端的项目,事实上,大错特错了,可能大家看到我什么都会,但是真的只是懂一些皮毛,而这些皮毛又恰好能支撑我做一些项目。经历了这么久全栈实习,发现可能并不适合我,或者说,我并没有到达那个能力。

为何选择 iOS 开发

为什么选择iOS,这是一个很玄学的问题,我是一个果粉,目前基本上所有设备都用苹果的。同时,我更喜欢 Swift 这门语言,说不出道理的喜欢。虽然 iOS 已经没人要了,但我依然热爱。

另一个原因是,想做一个用户体验很好的独立应用,而iOS生态能够很好的支持。

生活

少数派作者

在我写完第一个版本的番茄计后,我写了一篇宣传文稿发布在少数派上,同时又写了一篇效率有关的解决方案文章。因此加入了少数派 Matrix 作者群,成为了一名少数派作者

其他

认识了一个超级可爱的学妹qvq

新年目标完成情况

以上写于首都国际机场

Q4 计划

Q4 应该就是在学校了,这个季度应该主要 focus 在一些基础知识的学习,包括也不仅限于算法,数据结构,操作系统。同时也要开始看一些 Objective-C 的知识和 C++ 的内容。

目前我的个人项目有:

  • 日·期:这个 App 打算用 SwiftUI 和 Combine 进行重构,加入一些新功能,并且引入内购
  • 番茄计:重构!考虑使用 ReSwift 或者 RxSwift 进行重构,同时也规划了几个新功能
  • 博客:前端尝试 SwiftWebIUI,完善 UT,随缘加入一些功能
  • 一些试验性的项目:估计只会考虑写一下 demo

总而言之,不再仅仅做产品,而是借助做产品写代码去理解 API 和底层实现原理,同时巩固一些基础。

\ No newline at end of file diff --git "a/hexo.swift/Output/blogs/2019\345\271\264\347\273\210\346\200\273\347\273\223/index.html" "b/hexo.swift/Output/blogs/2019\345\271\264\347\273\210\346\200\273\347\273\223/index.html" new file mode 100644 index 0000000..8a439e1 --- /dev/null +++ "b/hexo.swift/Output/blogs/2019\345\271\264\347\273\210\346\200\273\347\273\223/index.html" @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

2019年终总结

发布于 2019-12-30

这一年,跟往年一样,没有坚持每天写日记的习惯,索性有 Google Photo 和 iCloud 帮我存了这一年的一些照片,也有各种社交网络保存了我这一年的一些记录。

2019 年的目标完成情况

先来看看去年的目标吧:

  • 学好 iOS 原生开发和 Flutter

这个目标,后来想想,根本不可能说自己已经学好了 iOS 原生开发,更别提 Flutter,仅仅只是用了一下

  • 每月一篇高质量的博客

目前有迹可循的今年的新博客只有 9 篇,不论质量,量就没有达到,质量上也只有两三篇可以称上中等吧

  • 学好英语,加入 SwiftGG 翻译组

记得有段时间,SwiftGG 是招人来着,不过要求是先翻译一篇文章

  • 有一套不错的摄影设备,尝试成为一个 Vloger

曾尝试用手机去拍一些 vlog,但是依然觉得自己对着镜头讲话是一件很奇怪的事情,更别提在大街上举着手机,而且自己也有点懒不想剪视频

  • 攒一笔旅游经费去一个没有去过的地方旅行

旅游经费算是攒出来了一小笔,但是没有时间旅行啊(呸,只是不是很想一个人出远门

  • 找一个女朋友

呵呵

下面是一些达成了的目标,具体这里先不展开讲

  • ✅Github 有一个不错的开源项目
  • ✅寒假看一些 CS 的基础知识,刷 Leetcode 200+ 题,春招的时候拿一个不错的 offer
  • ✅独立开发「Today is Boring」
  • ✅升级 Mac
  • ✅开发维护 A²OS 的开源项目
  • ✅拿到 WWDC Scholarship 去 Apple 总部和硅谷玩一趟

我的 2019

January & February

这两个月,基本是寒假吧,做了两个小项目:日·期和 SafeU。

日·期作为我第一个独立开发的应用,虽然是一个开始,但不算是一个很好的开始,最开始就想着做双端的应用,尝试了刚刚发布了正式版的 Flutter,写着写着发现自己写的太不规范,代码越写越烂,越写越看不懂,当把一些想好的功能都做完以后,匆忙上架了 App Store,也没有经过充足的测试,就让 Price Tag 帮忙推荐,前两天的下载量有 1.5k,其实自己感觉也挺爽的,但是两天之后几乎就没有下载量了,每天用的人也几乎没有,之后也因为不再想写 Flutter 就没有再去维护它。

SafeU 是我和老王、赵神还有冯神一起做的一个产品,而我负责了几乎所有的前端以及设计工作,对于我来说,做这个产品的初衷只是想让更多的同学来用,没错!只是想体验一下很多用户量的感受。我们去体验了竞品,也模仿了竞品,也做了一些创新的东西,也从技术上下了一些功夫,可惜,用户量一直没有上去。但至少,我今年所有打印传输任务都用它来完成了,不再用邮箱了,也算是一件不错的事。

March

这个月的主题应该就是 Prepare for WWDC2019 Scholarship,说实话真的没有指望能拿到,但是今年还是选择认真准备。思考了什么样的作品能够尽可能的入选,最后决定做一个关于强化学习的 Playground,所有的素材都用 iPad 手绘。

说实话,这并没有什么太多的创意,毕竟所做的本体是莫烦的强化学习课程的例子,用的算法也是最简单的 Q-learning,我所做的工作也只是把算法用 Swift 实现一遍,同时用 UIKit 实现了机器人走迷宫的 UI。其实工作量还是有一点的。

April & May

四月是大家的谎言,索性上帝还是眷顾我的,真的拿到了今年的 WWDC Scholarship,圆梦!

五月,确定了暑假实习的公司——依图,虽然不是预想的 iOS 岗,却也还不错(现在想来还是有点后悔的),毕竟还是能包住宿的,少了很多的麻烦吧。

June

六月,梦寐以求的 WWDC 之旅终于来了,人生第一次出国,人生第一次做飞机,认识了很多中国的学生开发者,也碰见了很多平时只能在网络上看到的大佬们,现在想来也还是很梦幻的。

July & August & September

这三个是我在依图实习的三个月,除了在北京依图的测试部门做了一些全栈开发的工作,我也做了一些 side projects。

首先是番茄计,做这个的初衷是看到了图拉鼎做的项目时间管理的工具,可是做着做着味道变了,功能完全变了,变成了一个番茄钟应用,同时也加入了一些我认为算是创新的点,最终,这个产品依然是匆匆上架,营收也并不好,截至目前为止也只有 50 多个付费用户,从产品角度,这简直是个烂产品,但是从技术角度看,我也做了两三次演变吧,学了很多的东西。

另一个就是现在的这个博客,之前用的是 Ghost,但是自从我坚定了走 iOS 这条路之后(更多的是 Swift?),于是开始关注 Swift Server Side 的一些东西,最后决定用 Vapor 写一个博客系统,虽然博客还是非常的简陋,但又不是不能用,毕竟也是受了 Yuu 的启发,想对 Vapor 的一些基础设施做一些工作。

在这三个月里面,也有了一些思想上的转变。因为在依图,996的生活的确让我很累,没有很多的时间用来做独立产品和出去闲逛,同时心里还是想做 iOS 开发而不是待在一个测试部门,做一些公司内部的工具。最终决定了还是参与秋招,每天晚上回去做算法题,复习基础知识,看各种面经,做各种笔试题,各种面试。投的一些公司也基本上是有双休的公司,而且只投 iOS 开发岗。最终收获了美团、流利说和 XMind 的 offer。

另一件有趣的事,因为开发番茄计,在少数派写了一篇文章来宣传番茄计,同时又写了一篇有关效率的文章,竟然成为了一名少数派 Matrix 作者。

October & November

回学校摸鱼养老的两个月,帮舍友写写课设,参加参加 Hackathon,用 SwiftUI 重写日·期等等,但是都没有什么成果吧。

这两个月唯一值得说的应该是我参与了 Swift 编译器的开发,当然只是简单的修了一个 starter bug,虽然不知道为什么 Contributor 里没有我,但是里面实实在在有我写的代码,还是很开心的,编译器真好玩!

December

秋招最后还是选择了美团的 offer,于是今年的最后一个月选择去美团实习了,同时在上海长租了一个房间,也算是在上海有了一个小小的家。

小结

我一直认为,做一款产品,自己首先要成为忠实的用户,而就我目前开发的这些产品,我觉得只有 SafeU 勉强称得上自己是忠实的用户。也不是说 SafeU 真的有多么的好,至少他是一款解决我生活中某些特定场景需求的产品。而我独立开发的那些产品,从一定意义上说,我只是为了开发而开发,并没有击中我生活中的痛点,在这一点来看我今年不算成功。

在今年的最后两个月,有幸参与了 Swift 编译器的开发,虽然仅仅是一个简单的 Starter Bug,但倒是发现了编译器非常的有趣,可能只是因为喜欢 Swift 这门语言。

今年唯一令我感到兴奋和开心的事就是去了 WWDC,认识了这么多年纪相仿的学生开发者,遇见了钟文泽、飞猪老师、魏布斯、钟颖等各路大佬,又在现场听了 WWDC 的 Keynote 和 Session,还参加了 Design Lab 和一些技术 Lab,在现场和 Apple 的工程师和设计师讨论。感受了美国独特的饮食、美好的天气以及风土人情。

今年的数码更新

  • 小米手环 -> Apple Watch
  • 小米 8 -> iPhone XR
  • AirPods -> AirPods Pro

今年看的电影

  • 流浪地球
  • 阿丽塔:战斗天使
  • 驯龙高手 3
  • 惊奇队长
  • 复仇者联盟4:终局之战
  • 何以为家
  • 大侦探皮卡丘
  • 蜘蛛侠:英雄远征
  • 上海堡垒
  • 速度与激情:特别行动
  • 中国机长
  • 我和我的祖国
  • 少年的你
  • 天气之子

今年看的电视剧番剧

  • 四月是你的谎言
  • 我们仍未知道那天所看见的花的名字
  • 我的英雄学院
  • 雨伞学院
  • 硅谷第六季
  • 神盾局特工第六季
  • 闪电侠第六季
  • 全职高手
  • 都挺好
  • 小欢喜
  • 庆余年
\ No newline at end of file diff --git "a/hexo.swift/Output/blogs/Codable \345\215\217\350\256\256/index.html" "b/hexo.swift/Output/blogs/Codable \345\215\217\350\256\256/index.html" new file mode 100644 index 0000000..59d208a --- /dev/null +++ "b/hexo.swift/Output/blogs/Codable \345\215\217\350\256\256/index.html" @@ -0,0 +1,45 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

Codable 协议

Swift

基础

发布于 2019-11-12

Codable 协议能实现基本的序列化和反序列化,Codable 其实是两个协议合一—— Encodable & Decodable

struct User: Codable {
+    var name: String
+    var age: Int
+}
+

只需要支持 Codable 协议,现在就可以将一个 user 序列化成 JSON 数据

do {
+    let user = User(name: "John", age: 31)
+    let encoder = JSONEncoder()
+    let data = try encoder.encode(user)
+} catch {
+    print(error)
+}
+

然后我们可以通过 JSONDecoder 进行反序列化

let decoder = JSONDecoder()
+let secondUser = try decoder.decode(User.self, from: data)
+

反序列化出来的 secondUser 应该和一开始我们定义的 user 是相同的,我们也可以看到输出序列化后的 data:

String(data: data, encoding: .utf8)!
+// {"name":"John","age":31}
+

但是有时候我们拿到的 json 不一定和我们定义的结构一致,比如我们拿到的 User JSON 长得像这样

{
+    "user_data": {
+        "full_name": "John Sundell",
+        "user_age": 31
+    }
+}
+

一种解决方法是,改我们的 User 结构体使得他符合该 JSON 的格式,当然这种方法优点不切实际。另一种选择我们可以扩展我们 User,添加一个专门用来做序列化和反序列化的类型:

extension User {
+    struct CodingData: Codable {
+        struct Container: Codable {
+      var fullName: String
+      var userAge: Int
+    }
+
+    var userData: Container
+  }
+}
+

然后给 User.CodingData 一个方法用来返回 User 实体

extension User.CodingData {
+    var user: User {
+        return User(
+            name: userData.fullName,
+            age: userData.userAge
+        )
+    }
+}
+

但是我们“键”不一样,但是我们可以通过 keyEncodingStrategykeyDecodingStrategy 来解决这个问题,设置成 convertToSnakeCase 即可

let decoder = JSONDecoder()
+decoder.keyDecodingStrategy = .convertFromSnakeCase
+
+let codingData = try decoder.decoder(User.CodingData.self, from: data)
+let user = codingData.user
+

参考文章

1. Codable | Swift by Sundell

\ No newline at end of file diff --git "a/hexo.swift/Output/blogs/SwiftUI\346\225\260\346\215\256\346\265\201\345\256\236\350\267\265/index.html" "b/hexo.swift/Output/blogs/SwiftUI\346\225\260\346\215\256\346\265\201\345\256\236\350\267\265/index.html" new file mode 100644 index 0000000..e766d51 --- /dev/null +++ "b/hexo.swift/Output/blogs/SwiftUI\346\225\260\346\215\256\346\265\201\345\256\236\350\267\265/index.html" @@ -0,0 +1,78 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

SwiftUI数据流实践

发布于 2019-10-19

前提

状态(State)是一个 App 中最关键的东西之一,比如我们要用 SwiftUI 来开一个音乐播放器,其中比较关键的是播放按钮,我们会有两个播放状态,播放和暂停,不同状态按钮的图片也是不同的

struct ContentView: View {
+	private var isPlaying: Bool = false
+
+	var body: some View {
+		Button(action: {
+			...
+		}) {
+			Image(name: isPlaying ? "pause" : "play")
+		}
+	}
+}
+

这里我们实现了最简单的根据 isPlaying 状态显示不同按钮图片的代码,但是我们如何通过按钮的点击事件来更新 isPlaying 状态?

@State

SwiftUI 通过 @State 来管理属性,当 state 值发生变化,界面也会随之更新,对于一个界面,state 是 single source of truth(并不知道该怎么翻译)

State 实例和它的值并不是等价的,获取它的值可以直接使用它的值属性

应该通过 view 的 body 或者方法来获取 state 属性。因此,建议将 state 属性定义成私有来防止其他 view 来获取它。

可以使用 binding 来绑定一个 state,或者使用 $ 前缀

所以,我们仅需在 Button 的 action 中 self.isPlaying.toggle() 来更新,同时也要给 isPlaying 使用 @State 的 property wrapper

struct ContentView: View {
+	@State private var isPlaying: Bool = false
+	
+	var body: some View {
+		Button(action: {
+			self.isPlaying.toggle()
+		}) {
+			Image(name: self.isPlaying ? "pause" : "play")
+		}
+	}
+}
+

当我当前这个 View 比较复杂时,我需要拆分组件,这时候我要把 Button 作为一个独立的组件,我们通过 command 点击 Button,使用 Estract Subview 来抽取组件

struct ContentView: View {
+    @State var isPlaying: Bool = false
+    
+    var body: some View {
+        HStack {
+            PlayerButton()
+        }
+    }
+}
+
+struct PlayerButton: View {
+    var body: some View {
+        Button(action: {
+            self.isPlaying.toggle()
+        }) {
+            Image(systemName: isPlaying ? "pause" : "play")
+        }
+    }
+}
+

但是 PlayerButton 缺少了 isPlaying 的状态。

@Binding

我们可以通过 SwiftUI 的另一个 Property Wrapper 来实现组件间状态的传递。

struct ContentView: View {
+    @State var isPlaying: Bool = false
+    
+    var body: some View {
+        HStack {
+            PlayerButton(isPlaying: self.$isPlaying)
+        }
+    }
+}
+
+struct PlayerButton: View {
+	@Binding var isPlaying: Bool
+
+    var body: some View {
+        Button(action: {
+            self.isPlaying.toggle()
+        }) {
+            Image(systemName: isPlaying ? "pause" : "play")
+        }
+    }
+}
+

特别需要注意的地方是,我们这边需要用上 $ 符号来做传递。

但是这样做会有一些问题 1. 如果我嵌套了好几级组件,而我最里层的组件需要用到的状态是在最顶层设置的,那么我们需要一级一级的往下传递,而中间几层又并不需要这个属性,就导致了在组件的定义中添加不必要的属性,降低了代码的可读性 2. 状态零散的散布在各个 View 中,不利于管理

@ObservedObject

当我们的状态比较复杂后,又或者我们需要在多个界面共享状态时,我们需要用到 @ObservedObject,这里似乎是借鉴了 Redux 的思想,我们会定义一个 Store 用来做全局的状态存储,为了能够让它可以使用 @ObservedObjet 我们需要遵循 ObservableObject  协议,然后把我们的 isPlaying 属性放到 Store 中存储

final class Store: ObservableObject {
+	@Published var isPlaying: Bool = false
+}
+

然后将 @State var isPlaying: Bool = false 替换成 @ObservedObject var store = Store() 即可

struct ContentView: View {
+    @ObservedObject var store = Store()
+    
+    var body: some View {
+        PlayerButton(isPlaying: self.$store.isPlaying)
+    }
+}
+

但是这样做依然解决不了组件间需要不断传递这个 Store 的问题,我的解决方案很简单,使用单例

final class Store: ObservableObject {
+	static let shared = Store()
+
+	@Published var isPlaying: Bool = false
+}
+

这样我们在需要的地方,获取这个 Store.shared 中的属性,对其修改后也能在其他页面作出相应的修改。

小结

以上算是我近一个月用 SwiftUI 写 side projects 时的一些心得,主要是 @State@Binding@ObservedObject 这三个 property wrapper 在 SwiftUI 数据流中的使用

参考资料

  1.  Managing Data Flow in SwiftUI
  2. WWDC2019 Session 226 Data Flow Through SwiftUI
  3.  What’s the difference between @ObservedObject, @State, and @EnvironmentObject?
\ No newline at end of file diff --git a/hexo.swift/Output/blogs/Test/index.html b/hexo.swift/Output/blogs/Test/index.html new file mode 100644 index 0000000..d8e70c9 --- /dev/null +++ b/hexo.swift/Output/blogs/Test/index.html @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

Test

发布于 2020-03-08

my blog

测试

\ No newline at end of file diff --git a/hexo.swift/Output/blogs/This is another test/index.html b/hexo.swift/Output/blogs/This is another test/index.html new file mode 100644 index 0000000..bfcd273 --- /dev/null +++ b/hexo.swift/Output/blogs/This is another test/index.html @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

This is another test

发布于 2020-03-16

This is another test

hahahha

\ No newline at end of file diff --git a/hexo.swift/Output/blogs/about/index.html b/hexo.swift/Output/blogs/about/index.html new file mode 100644 index 0000000..d0e56ee --- /dev/null +++ b/hexo.swift/Output/blogs/about/index.html @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

about

about

发布于 2020-03-15

This is About

\ No newline at end of file diff --git a/hexo.swift/Output/blogs/index.html b/hexo.swift/Output/blogs/index.html new file mode 100644 index 0000000..a9294dd --- /dev/null +++ b/hexo.swift/Output/blogs/index.html @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

2019年终总结

没有变秃也没有变强

Codable 协议

简单了解了一下 Codable 协议如何进行 JSON 的序列化与反序列化

SwiftUI数据流实践

近一个月在使用 SwiftUI 重构我原先使用 Flutter 写的独立开发应用「日·期」,这篇文章总结了我的使用心得

2019Q3报告

这是一个季度总结

实现一个开方算法

昨天参加美团三面,感觉这道算法题很不错,虽然难度不大,但是也有一定的技巧

\ No newline at end of file diff --git a/hexo.swift/Output/blogs/test001/index.html b/hexo.swift/Output/blogs/test001/index.html new file mode 100644 index 0000000..04a1bb5 --- /dev/null +++ b/hexo.swift/Output/blogs/test001/index.html @@ -0,0 +1,2 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

test001

发布于 2020-03-14

hello world!

print("233")
+
\ No newline at end of file diff --git "a/hexo.swift/Output/blogs/\345\256\236\347\216\260\344\270\200\344\270\252\345\274\200\346\226\271\347\256\227\346\263\225/index.html" "b/hexo.swift/Output/blogs/\345\256\236\347\216\260\344\270\200\344\270\252\345\274\200\346\226\271\347\256\227\346\263\225/index.html" new file mode 100644 index 0000000..dfbcee7 --- /dev/null +++ "b/hexo.swift/Output/blogs/\345\256\236\347\216\260\344\270\200\344\270\252\345\274\200\346\226\271\347\256\227\346\263\225/index.html" @@ -0,0 +1,26 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

实现一个开方算法

发布于 2019-08-28

题目

昨天参加美团三面,有一道算法设计题,题目是这样的

func sqrt(x: Double) -> Double
+

实现一个方法,输入输出为Double类型,方法的功能是返回输入值X的开方,不能调用接口,不需要想数学方法,仅需简单的算法进行实现。

第一步

拿到这道题,面试官给我3min时间思考,一上来就有思路,用二分来解决,那么首先要确定二分的左右边界是什么,这里就要注意了,X < 1X > 1的情况要分开来考虑: - 当 X < 1 时,左边界为X,右边界为1; - 当 X > 1 时,左边界为1,右边界为X;

第二步

当我把这个思路和面试官说完以后,面试官对这一步骤表示认可,于是抛出下一个问题,二分什么时候退出呢?然后我下意识的问了一句,有什么精度要求嘛?面试官答,那我们就要求精度为1e-8 吧。

我一开始把精度理解成了保留小数点后几位,于是尴尬的事情发生了:

我的第一想法是,把二分的结果乘以1e-8,然后看它是不是整数,被面试官否定了。

我的第二想法是,把二分的结果转换成字符串,然后判断位数,又被否定了。

面试官于是给出提示,从二分本身考虑,于是想到,所谓精度只是一个误差范围,那么在二分过程中,如果左右边界之差小于1e-8就意味着达到了精度。

以上就是整个算法的思路

第三步

第三步是要求分析这个算法的复杂度,我计算的时候直接给出了这样的公式

2^n * 10^-8 = |x-1|
+

完整代码

回去之后用 Swift 实现了一遍

func sqrt(x: Double) -&gt; Double { 
+    if (x < 1) {
+        return half(left: x, right: 1, x: x)
+    } else if (x > 1) {
+        return half(left: 1, right: x, x: x)
+    } else {
+        return 1
+    }
+}
+
+func half(left: Double, right: Double, x: Double) -&gt; Double {
+    let middle = (left + right) / 2
+    if (right - left < 1e-8) {
+        return middle
+    }
+    if (middle * middle > x) {
+        return half(left: middle, right: right, x: x)
+    } else if (middle * middle &gt; x) {
+        return half(left: left, right: middle, x: x)
+    } else {
+        return middle
+    }
+}
+
\ No newline at end of file diff --git a/hexo.swift/Output/friends/index.html b/hexo.swift/Output/friends/index.html new file mode 100644 index 0000000..58cec47 --- /dev/null +++ b/hexo.swift/Output/friends/index.html @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

friends

\ No newline at end of file diff --git a/hexo.swift/Output/index.html b/hexo.swift/Output/index.html new file mode 100644 index 0000000..568774a --- /dev/null +++ b/hexo.swift/Output/index.html @@ -0,0 +1 @@ +Welcome to Ninjiacoder's Home!

Ninjiacoder

Swift lover, Fullstack Developer

Hello.

My name is Ziyuan Zhao

I am a fullstack developer and a Swift lover. Now I'm an intership @meituan. Here is my @blog

I'm also an independent developer. I have two iOS app, tomatic & TodayMatters

I'm one of the creators of NUAA Open Source. As a core developer, we have developed a cloud U-disk called SafeU

Besides, I'm a fan of Marval & DC. I like playing games on PS4

You can find me @Telegram, @Github, @Twitter, @Weibo, @Zhihu

\ No newline at end of file diff --git a/hexo.swift/Output/style.css.tmp.html b/hexo.swift/Output/style.css.tmp.html new file mode 100644 index 0000000..a24f8d7 --- /dev/null +++ b/hexo.swift/Output/style.css.tmp.html @@ -0,0 +1,431 @@ +