20180701_ARTS_week01

ARTS 是耗子哥(左耳朵耗子)发起的一个活动。 A -- Algorithm 每周一道算法题 R -- Review 每周阅读并点评一篇英文技术文章 T -- Tip 每周学习一个技术技巧 S -- Share 每周分享一篇技术文章 坚持一年 :-) 这是我的第一周 ARTS

Algorithm

Two Sum Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

先审题,要从一个数组里面找到满足想加等于某个数的两个数的位置。第一想法是遍历两遍,这样肯定可以,但是时间复杂度是 O(n^2),我们直接想想有没有更优化的方法。

一般做这种需要多重循环的,有两个可以考虑的优化方向: 1. 不要让这次循环浪费,记录下这次循环的值,后面可能有用; 2. 缩小每次需要循环的集合。

这里刚好适合第一种,把循环了又暂时没用到的值作为字典的 key 中,把位置作为对应 key 的 value。

这里还有个问题,数组的值可能是重复的,但下标不同,如果放到字典里,后面的值和位置会替代前面的值。于是有了下面这种,用了两个字典实现。

var twoSum = function (nums, target) {
    var numDict = {},
        numDictRepeat = {}
    for (var i=0; i<nums.length; i+=1) {
        // numDict[nums[i]] = i; // key: integers, value: the indice position

        var curVal = nums[i]
        if (typeof numDict[curVal] !== "undefined") {
            numDictRepeat[curVal] = i
        } else {
            numDict[curVal] = i
        }

        var num2Pos = numDict[target - curVal]

        if (typeof num2Pos !== "undefined" && num2Pos !== i) {
            if (num2Pos === i ) {
                num2Pos = numDictRepeat[target - curVal]
            }
            return [i, num2Pos].sort()
        }
    }
    return []
};

var nums = [3,3], target = 6
rs = twoSum(nums, target)
console.log(rs)

可以看到,用两个数组其实非常搓,只是为了规避两个数相同的情况,那么可以稍微改一下,当相同并且满足相加条件的时候就 return。

var twoSum = function (nums, target) {
    var history = {}
    for (var i=0; i<nums.length; i+=1) {
        var curVal = nums[i]
        if (typeof history[curVal] !== "undefined" &&  (curVal + curVal) == target ) {
            // 同数不同位置,想加又刚好是 target 3+3=6
            // if (curVal + curVal == target) {
            //     return [history[curVal], i]
            // }
            return [history[curVal], i]
        } else {
            // key: integers, value: the indice position
            history[curVal] = i
        }

        var num1 = nums[i],
            num2Pos = history[target - num1]

        if (typeof num2Pos != "undefined" && num2Pos != i) {
            return [num2Pos, i]
        }
    }
    return []
};

// [3,3],[3,2,4]
var nums = [2, 7, 11, 15], target = 9
rs = twoSum(nums, target)
console.log(rs)

写完再看一下,上下其实有两段一样的 if 判断,造成这样原因是我过于聚焦把循环的值给放到字典里面了,其实可以现判断是否满足条件,满足就搞定返回,不满足才记录到字典里。

于是有了下面这种写法。

var twoSum = function (nums, target) {
    var history = {}
    for (var i = 0; i < nums.length; i += 1) {
        var curVal = nums[i],
            num2Pos = history[target - curVal]

        if (typeof num2Pos != "undefined") {
            return [num2Pos, i]
        }
        history[curVal] = i
    }
    return []
};

// [3,3] = 6, [3,2,4] = 6
var nums = [2, 7, 11, 15], target = 9
rs = twoSum(nums, target)
console.log(rs)

总结一下,为什么一开始就抛弃了两重循环的想法,因为我觉得一个工程师是应该有识别方案好坏的能力,一些一看就不是最好的办法,只是在实在没有别的方案的时候才采用,如果能一眼就看出某个方案的好坏,何必把好方案和坏方案放在一起优良中差的硬比一遍呢。

除此之外,虽然知道如何做是更优的方法,但也要跳出方法,回归整体逻辑,不要像这题一开始那样由于关注点过于集中在把数值记录在字典中,从而绕了些弯路。不过经历了把代码逐渐优化写短的过程,还是有点小开心的。

Review

The deepest reason why modern JavaScript frameworks exist

这篇文章把 Vue, React, Angular 称为现代前端框架,主要用一个用户输入 email 地址,列表记录和修改地址的例子来说明『现代前端框架出现主要是为了解决页面状态和 UI 的同步问题』。

主要说了以前的方式会有很多代码用在 HTML 的拼接生成上,易出错以及难以维护。

然后用了一个小例子来描述如何利用 virtual-dom 来更新页面的过程,这个例子对理解组件更新有一些启发。

说说个人观点,更方便的『页面状态和 UI 的同步』只是现代前端框架带来的一个小功能,没有这些框架之前也可以做到正确的渲染,比如用一个函数专门负责渲染,或者 Handlebar.js 等模板库,毕竟正确的渲染是最基本的功能。

我个人理解现代前端框架的出现,给前端带来了组件化,工程化,性能(比如 virtual-dom)上更多的思考,同一个框架组件有更统一的标准和 API,也为前后端分离提供了更加通用的解决方案。

至于原因,我觉得是前端技术演化的结果。随着科技的发展,PC 或手机性能越来越强,前端页面所承载的功能也越来越多,有点像安迪-比尔定律(硬件提高的性能,很快被软件消耗掉了),业务复杂度的上升和对良好用户体验的不断追求带来前后端分离,首屏渲染,异步加载,单页面应用等需求,于是产生了一批代码维护更加便捷,组件化更加清晰的现代前端框架。至于『页面状态和 UI 的同步』,是在这过程中是为了提高生产力,把前端从频繁又繁琐的页面更新上解放出来的一剂良药。

Tip

本周记录一个工作中遇到的小 Tip。

工作中有一次把一个分支,称为 feature1,merge 到主干的时候,发现发生了 fast-forward,没有合并记录。原因是不久前 feature1 分支合并过主干,主干和 feature1 不存在分叉,但主干落后于 feature1,所以就直接 fast-forward 了,没有产生新的 commit。

工作中我们是要求主干上的合并都要留有记录,可以用命令 git merge --no-ff 来禁止本次 merge 的 fast-forward。

有时候你可能会忘了添加 --no-ff 参数,也可以设置一下,git config branch.master.mergeoptions "--no-ff" 直接 merge 的时候禁止 fast-forward。

Share

近日,Airbnb 宣布弃用 React Native,原文地址 Sunsetting React Native

我现在是做移动端 web 开发,混合 APP 是主要的业务形态。

我以前用过一下 PhoneGap (后改名 Cordova),上上年也在公司内尝试使用 React Native,最近一些业务上还尝试了 Weex。JavaScript 一统世界似乎一直是前端界不断努力的方向,然而总是不尽如人意。现在依稀能回忆起第一次听说 React Native 时那种兴奋,以及第一次跑通 React Native 例子时感叹其开发体验之好。

然而,事实总是残酷的。软件工程中时间,成本,质量三者最多能做到两个,有时候是一个,有时候一个都做不到。使用 React Native 后,相比终端来讲,做页面的时间肯定是快了,基本兼容 iOS/Android 成本也低了,但是质量却不太行,主要遇到几个问题:

1. 坑比较多,有平台兼容性的,有 React Native 本身的,缺少完善的 debug 工具,debug 耗费的时间较多;
2. 以前终端提供给 web 的接口,需要再封装一遍提供给 React Native;
3. React Native 相比纯终端,能力上都有很大限制,有些能力不具备的时候,需要终端提供支持,比如视频播放器,音频播放器;
4. 我们比较注重页面打开速度,React Native 首次进入的速度不如做了一些优化的 Web,二次进入的速度会好很多,
5. 一些比较复杂的交互无法实现,动画能力较弱。

除了以上问题,React Native 的确在 View 层的开发便捷性上要比原生好不少。如果你想要用在项目中,最好根据实际需求场景,在一些交互要求不高,View 层以展示为主的二级页面上先进行试水。

最后在多唠叨几句,不管 React Native 又或者阿里推出的 Weex,前端只是 View 层,实际上都是靠终端驱动的技术,要想真正用好他们,还需要同时熟悉 iOS 和 Android 相关知识。现阶段,前端想靠 JavaScript 一统天下还是不现实的,所以前端程序员们还是要拓展自己的能力边界,不要整天就会写页面写 CSS,比如学以学习原生开发 :-)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏互联网杂技

JavaScript就要统治世界了?

" JavaScript 可以……" "嘛,不就是操作一下 DOM,可以让元素飞来飞去吗" "JavaScript 是……" "不就是用 jQuery 让网页动...

35260
来自专栏小古哥的博客园

微信小程序-实战巩固(二)

刚刚写了小程序入门没几天,小程序就开放个人开发者资格,感觉为我而来啊 \(≧▽≦)/。迫不及待的去注册,准备将之前的处女作传上去体验一把,结果卡在了服务器配置上...

46470
来自专栏司想君

2017年前端开发手册(二)-2017前端技术展望

1. Web Assembly, 获取刚刚到达顶峰。 2. `import`可能仅仅被用在`<script></script>`中。 3. 通用JavaScri...

36360
来自专栏静晴轩

如何写一手漂亮的 Vue

前几日听到一句生猛与激励并存,可怕与尴尬同在,最无奈也无解的话:“90后,你的中年危机已经杀到”。这令我很受触动。显然,这有些夸张了,但就目前这日复一日的庸碌下...

82260
来自专栏较真的前端

RxJS福利~~

1K50
来自专栏Android先生

从小白到独立开发Android和IOS两种平台app过程与总结

16年上半年在帮老师,帮外面随便做点东西以便得到些生活费养活自己。下半年去外面公司待了一段时间,然后选择回来帮自己做个东西,历时三个月,独自完成安卓及IOS版本...

18710
来自专栏IMWeb前端团队

关于Uinicode的一个“有趣的”事情

本文作者:IMWeb 黄龙 原文出处:IMWeb社区 未经同意,禁止转载 故事是这样开始的 产品K: 为什么我们的网站不能显示火星文? 开发L: 什么样的火星文...

22850
来自专栏HT

基于HTML5的燃气3D培训仿真系统

最近上线了的基于HTML5的燃气3D培训仿真系统,以前的老系统是采用基于C++和OpenGL的OpenSceneGraph引擎设计的,OSG引擎性能和渲染效果各...

25050
来自专栏Nian糕的私人厨房

Vue2.0 歌手数据获取及排序

本次的系列博文的知识点讲解和代码,主要是来自于 黄轶 在慕课网的 Vue 2.0 高级实战-开发移动端音乐WebApp 课程,由个人总结并编写,其代码及知识点...

9730
来自专栏BeJavaGod

以最简单的登录为例,诠释JS面向对象的简单实例

JavaScript,是前端开发人员必须会的一门技术,从JS演变出来的有很多框架,先说说几个热门的框架吧: JQuery:这个技术必须会,如果不会,那一定要会查...

34670

扫码关注云+社区

领取腾讯云代金券