给定两个数字,求这两个数的二进制数相应位不同的总数。

注意:
$0 \leq x, y < 2^{31}$

例子:

输入: x=1, y=4
输出: 2

解释:
1 (0 0 0 1)
4 (0 1 0 0)
^ ^
上面箭头指的位置相应两个数字的二进制位不一样,一共有2处。

##解法1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// javascript
/**
* @param {number} x
* @param {number} y
* @return {number}
*/
var hammingDistance = function(x, y) {
let xor = x ^ y;
let count = 0;
while(xor !== 0) {
count += xor & 1;
xor = xor>>1;
}
return count;
};

首先通过异或操作得到一个值xor。
在循环里面判断有几个不一样的位置。
从最后一位开始判断,直到所有位置判断完成。

##解法2:

1
2
3
4
// javascript
var hammingDistance = function(x, y) {
return (x ^ y).toString(2).replace(/0/g, '').length;
};

第一步同解法一。
第二步转换成操作字符串的操作。
删除’0’,随后判断字符串的长度,即不同位置数。

##解法3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//javascript
/**
* @param {number} x
* @param {number} y
* @return {number}
*/
var hammingDistance = function(x, y) {
let xor = x ^ y;
let count = 0;
while(xor) {
count++;
xor &= xor-1;
}
return count;
};

其实这个问题可以简化成找出二进制数中有几个‘1’。比如异或结果是‘1010’,其中有2个‘1’表示hamming distance是2。

这段代码while循环可能一眼看上去发现自己懵逼了。其实xor &= xor-1;这个操作是移除一个’1‘。有几个就是移除几次。如果还懵逼,可以多调试几次。

给定一组数和一个目标值,求出两个加数的位置。

比如:

1
2
3
nums = [2, 7, 11, 15], target = 9
因为nums[0] + nums[1] = 2 + 7 = 9,
返回 [0, 1]

注意返回的位置是基于0的

##方法一 O(n^2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
for (var i=0; i<nums.length; i++) {
for (var j=i+1; j<nums.length; j++) {
if ((nums[i] + nums[j]) == target) {
return [i, j];
}
}
}
};

##方法二 O(n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
let map = new Map();
for (var i=0; i<nums.length; i++) {
let nextNum = target - nums[i]

if (map[nextNum] !== undefined) {
let result = []
result.push(map[nextNum])
result.push(i)
return result
}

map[nums[i]] = i
}
};

##总结
方法二巧妙利用hashMap取值的时间是固定的这一特点。把复杂度从O(n^2) 降到了O(n)。

从学习iOS开发就开始接触到MVC的开发模式了。随着越来越注重用户体验以及业务越来越复杂。ViewController也越来越臃肿,同时我们的工作量也越来越大。在ViewController中混杂着业务逻辑与UI处理的逻辑。完整的测试ViewController既要对UI进行测试也需要对业务逻辑进行测试。测试起来比较麻烦。

物极必反 器满则倾

接下来进入正题,看看MVVM设计模式是如何解决这些问题的。

MVVM = Model + View + ViewModel

看上去和MVC差不多,就是把ViewController替换成了ViewModel。如果是这样的话,MVVM压根就没有存在的必要了。所以并不是进行了简单的替换。MVVM由3部分组成:Model , View , ViewModel。

  • Model: 作为数据的容器
  • View: 负责界面的展示以及用户交互的处理
  • ViewModel: 负责业务逻辑处理

##iOS中的MVVM

然并卵iOS中我们没有办法绕过UIViewController。诸如UITabController, UINavigationController是非常非常常用的。没有这些容器,我们写界面时的情景简直不敢想象。IB与UIViewController的结合比较紧密。如果你通过IB来画界面的话,更离不开UIViewController。那么iOS中的MVVM是什么样的?

图:捂脸

  • Model: 作为数据的容器
  • View: 负责界面的展示以及用户交互的处理
  • ViewController: 用代码创建视图;胶水代码,连接View和ViewModel
  • ViewModel: 负责业务逻辑处理

Model,View,ViewModel的职责都没有改变。iOS的MVVM开发模式中ViewController只做与视图有关的操作,以及连接View与ViewModel的胶水代码。也就是说View部分其实是由原本的View+部分ViewController组成。

一旦我们这样组织代码,首先进行业务逻辑测试的时候我们只需要测试ViewModel就可以。测试UI只需要测试View+ViewController。对于UI的自动化测试我一直没有找到什么特别好的办法,可能主要靠手工和一些第三方的测试平台吧。其次我们在开发过程中可以进行并行开发了,即可以同时开发界面和业务逻辑。即使你是一个人开发App,那么每一次只做一件事情同样会让你的头脑更清楚。

图:开心

##胶水代码

iOS中没有胶水代码的MVVM是不完整的

胶水代码都做了哪些事情?

  1. 将控件的事件传递给ViewModel,使得ViewModel其有机会处理用户交互。
  2. 将ViewModel的内容与View进行绑定,使得View有机会显示正确的内容。

在ReactiveCocoa出来之前,胶水代码很难写的很优雅。这也是为什么以前iOS中MVVM并不怎么火的原因。关于ReactiveCocoa的学习与使用本文不会涉及。如果有需要可以自行搜索学习。它是响应式开发的利器。

iOS的MVVM开发模式不能没有”ReactiveCocoa”

没有胶水代码,你不能将业务逻辑从ViewController中抽离。

也谈谈MVVM(二)将会进行实战演练。结合一个简单的Demo进行讲解MVVM开发模式。敬请期待!另外欢迎大家能和我一起讨论交流,一起进步。

未完待续…

图:三只企鹅

  1. 是什么
  2. 能做什么
  3. 配置步骤
    devloper 配置appid
    iTunesConnect创建app
    iTunesConnect创建内购商品 注意是产品id,不是appid
  4. 开发步骤
    SKProductsRequest
    paymentQueue:updatedTransactions: 事务处理,完成之后调用finish
  5. 开发进阶/事务
  6. 开发进阶/防破解

我们公司在南京招聘iOS的时候,人真难找啊。而我也一直有想开设一个培训班的想法。乘着现在不想写代码。写一篇iOS学习路线图的文章。同时也决定出一系列的学习教程。

iOS开发的人相对于以前来说已经慢慢多起来了。但是不管从质量还是数量上来说都明显感觉不够。大学里面应该很少有iOS开发课程的。iOS开发前期投入比较高——你得先买一台苹果电脑才能开始学习iOS开发。这些限制使得iOS程序员数量跟不上企业的需求。由于物以稀为贵,这也使得iOS程序员的工资普遍也还不错。

言归正传,上学的时候我看了不少学习方法的书。其中无非就是以下几点:

  1. 学习新知识
  2. 总结新知识
  3. 重复的练习
  4. 融汇总结知识

这个系列的教材我将按照这些学习规律进行设计。本系类教材内容主要是帮助零基础的同学进入iOS开发的领域,并能通过它找到一份能让你养家糊口的工作。教材的前期会快速的带大家进入iOS开发。以便在你学习热情还没有消散的情况下让你快速入门。后面会逐渐补充上对大家以后有帮助的知识。换句话说,前面部分是让你会走,而后面部分是让你走的更远。同时在大家能做项目的时候,我也会附上我工作中的一些经历与感受。希望能让大家在工作上少走点弯路。

啰嗦了这么多,接下来看看教程的列表。

阶段一:学习语言

零基础的人首先可以快速的学习C语言,从而了解什么是编程语言。如何使用编程语言与计算机进行交流,并指导其完成机械的任务。学习完这一阶段之后我们可以使用编程语言来完成一些简单的任务。

  1. C语言
  2. Swift语言
    阅读全文 »

iOS App在打开的时候一般会显示一张启动图片。这样用户会觉得程序打开速度和响应速度很快。启动图片只有一个用途就是让用户觉得程序响应很快,除此之外没有其他作用。

启动图片的内容

启动图片能帮助我们提高App的用户体验,接下来我们看看启动图片应该是什么样子的。
在启动图片中,我们不应该用来提供这些内容:

  1. 一些进入的效果,如一个被溅射的屏幕
  2. 关于窗口
  3. 一些打上烙印的元素。(除非这些元素出现在即将出现的第一个程序界面。)
阅读全文 »

常常想把自己看的书记录下来,一直想下一次记,然后就没有然后了。现在先记下来再读吧。:D

  1. 《Swift Development with Cocoa》2014/12/24 - 2015/2/12
  2. 《程序员修炼之道》2015/4/15 - 2015/5/6

  1. 登录到 iPhone Developer Connection Portal(http://developer.apple.com/iphone/manage/overview/index.action )并点击 App IDs

  2. 创建一个不使用通配符的 App ID 。通配符 ID 不能用于推送通知服务。例如, com.itotem.iphone

  3. 点击App ID旁的“Configure”,然后按下按钮生产 推送通知许可证。根据“向导” 的步骤生成一个签名并上传,最后下载生成的许可证。

    阅读全文 »

1
2
3
4
5
6
7
for(NSString *familyName in [UIFont familyNames]){
NSLog(@"Font FamilyName = %@",familyName); //*输出字体族科名字

for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]){
NSLog(@"\t%@",fontName); //*输出字体族科下字样名字
}
}

最近想开始折腾Swift了。所以整理整理学习笔记。不得不说Swift确实比Objective-C简洁啊。在OC中Closure已经用的比较多了,每次声明的时候都是长长一串。现在终于不用那么麻烦了。不废话了,先来看看Closure的语法吧。

Closure表达式语法

1
2
3
{ (parameters) -> return type in
statements
}

简单吧。由于Swift编译器可以推断出变量的类型,所以我们有更简单的写法。

阅读全文 »
0%