<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[王二东的博客]]></title><description><![CDATA[寂寞守云日，方待月明时。]]></description><link>https://blog.youkuaiyun.com/WangErice</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; WangErice]]></copyright><item><title><![CDATA[“\“在字符串表示正则语义中的作用]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/160617211</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/160617211</guid><author>WangErice</author><pubDate>Wed, 29 Apr 2026 11:21:29 +0800</pubDate><description><![CDATA[在多数语言中，字符串中的"\"会作为转义字符串出现，用以将紧跟其后的字符转义，拓展字符的使用范围。但是在表示正则语义时，"\"会让一些使用场景显得很别扭.]]></description><category></category></item><item><title><![CDATA[Swift 中自定义运算符]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/115628366</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/115628366</guid><author>WangErice</author><pubDate>Mon, 12 Apr 2021 17:16:54 +0800</pubDate><description><![CDATA[Swift中自定义运算符相等运算符==
相等运算符==
在swift中，对于值类型(主要指结构体和枚举类型)，在使用过程中总是会通过复制来进行传递，可以直接通过相等运算符来判断两者是否相等;而由于类类型是引用类型，所以并不能直接使用相等符号来进行判断.

...]]></description><category></category></item><item><title><![CDATA[二进制重排优化]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/113349257</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/113349257</guid><author>WangErice</author><pubDate>Thu, 28 Jan 2021 18:11:30 +0800</pubDate><description><![CDATA[二进制重排优化虚拟内存非法内存访问内存浪费ASLR二进制重排二进制重排原理如何判断缺页中断耗时使用Instruments工具设置Xcode调试参数如何查看自己工程的符号顺序如何改变二进制符号的加载顺序获取启动期间加载的所有符号编写order文件
在早期的操作系统中，任何进程被加载到内存中运行时，都是按照顺序完全加载的。内存中的地址就是真实的物理地址，并且进程所需要的全部指令和数据都是一次性加载到内存中。这样就会有出现两个明显的问题：

数据安全问题： 由于各个进程是按照顺序依次加载到内存中的，并且内存中的地]]></description><category></category></item><item><title><![CDATA[静态代码插桩]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/113204871</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/113204871</guid><author>WangErice</author><pubDate>Wed, 27 Jan 2021 18:28:52 +0800</pubDate><description><![CDATA[静态代码插桩设置插桩参数
代码插桩是指根据一定的策略在代码中插入桩点来统计代码覆盖的技术手段.一般可以分为三个粒度：

函数(function): 按照函数为单位进行插桩；
基本块(basic block): 按照代码执行单元进行分组的执行单元，单元内部的代码执行次数一定是相同的；
边界(Edge): 按照代码执行路径进行插桩。

针对iOS来说，clang支持以上粒度的插桩方式。这里先介绍一些函数粒度的插桩实现.
设置插桩参数
clang是LLVM的一个轻量级的

...]]></description><category></category></item><item><title><![CDATA[AutoreleasePool实现原理]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/113178135</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/113178135</guid><author>WangErice</author><pubDate>Tue, 26 Jan 2021 16:55:24 +0800</pubDate><description><![CDATA[AutoreleasePool自动释放池是如何运作的pop
AutoreleasePool,根据名字可以知道这是一个自动释放池，起作用就是延缓自动释放池中对象的释放时机。
自动释放池是如何运作的
在iOS开发中，最经常见到的AutoreleasePool就是存在于main函数中的这个：
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        // Setup]]></description><category></category></item><item><title><![CDATA[查找二叉树子节点的最近共同父节点]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112687930</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112687930</guid><author>WangErice</author><pubDate>Fri, 15 Jan 2021 23:26:54 +0800</pubDate><description><![CDATA[查找子节点的共同父节点分析实现算法复杂度其他算法题目升级
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为：“对于有根树 T 的两个结点 p、q，最近公共祖先表示为一个结点 x，满足 x 是 p、q 的祖先且 x 的深度尽可能大（一个节点也可以是它自己的祖先）。”

实例1

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。

实例2

输]]></description><category></category></item><item><title><![CDATA[instancesRespondToSelector:与respondsToSelector：]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112556426</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112556426</guid><author>WangErice</author><pubDate>Wed, 13 Jan 2021 17:42:21 +0800</pubDate><description><![CDATA[instancesRespondToSelector:与respondsToSelector：查看源码实现object_getClass(id obj)结论instancesRespondToSelector:respondToSelector:
由于iOS是一门运行时语言，所以就不可避免地需要用到自省方法来判断当前消息是否可以被处理.其中用于判断方法是否是可以被响应的一个重要方法组就是instancesRespondToSelector:和respondsToSelector:,这两个方法在使用上是否相同]]></description><category></category></item><item><title><![CDATA[阿里二面]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112449358</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112449358</guid><author>WangErice</author><pubDate>Mon, 11 Jan 2021 00:02:04 +0800</pubDate><description><![CDATA[阿里二面实现细节算法
实现细节
这一次相对于一面来讲，涉及到项目中的技术实现细节更加深入，对于实现的数据分析和逻辑漏斗追问的更加详细，由于时间比较紧张准备不足，这次面试中的技术点交流并不流畅，有些实现细节描述不清，估计会止步于此.
算法
这次提到最长回文字串的查找，这是一道非常常规的算法题，然而由于过于紧张只记得Manacher算法，但是对于具体的查找实现没能描述清楚，超级尴尬.
其实面试官并不要求你会最牛逼的算法，只要有思路即可。比如这样一种实现：
// 判断s中索引[i, j]是不是回文序列
bool ]]></description><category></category></item><item><title><![CDATA[NSArray类簇]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112442705</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112442705</guid><author>WangErice</author><pubDate>Sun, 10 Jan 2021 22:29:23 +0800</pubDate><description><![CDATA[NSArray 类簇NSArray, NSMutableArray
类簇(class clusters)是抽象工厂模式在iOS下的一种实现，试图将多个类的实现统一在一起，对外只暴露简单的使用接口，隐藏类的真实实现。iOS中的NSArray，NSDictionary，NSArray以及NSNumber中都使用了这种实现。这里主要看一下数组的大概实现
注： 以下数据使用64位模拟器演示.
NSArray, NSMutableArray
在iOS中，NSArray, NSMutableArray的实现中包含了很多]]></description><category></category></item><item><title><![CDATA[阿里iOS一面]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112392574</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112392574</guid><author>WangErice</author><pubDate>Sat, 09 Jan 2021 15:53:15 +0800</pubDate><description><![CDATA[阿里iOS一面电话内容笔试
电话内容
基本上简历上写的内容都可能会聊到，会针对你擅长的某一个技术点做一些场景问答，所以写在简历上的都要做深入的探究。
笔试
笔试有两道题，也都相对简单：

以下代码输出的内容是什么，为什么？

NSString *a = @"test";
NSString *b = @"test";
if (a ==b) {
	NSLog(@"Equal");
} else {
	NSLog(@"Not Equal");
}

对于这题的答案，其实最初感觉字面量会被作为常量常量处理，这部分值]]></description><category></category></item><item><title><![CDATA[block究竟是不是对象?]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112391363</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112391363</guid><author>WangErice</author><pubDate>Sat, 09 Jan 2021 15:01:54 +0800</pubDate><description><![CDATA[block究竟是不是对象？blockblock结构block的继承关系结论
block
block是OC中经常使用到的一个实现，其实用更多的时候像是一个函数实现。而事实上，在更多的场景中，block的使用似乎更加接近于对象.那么block究竟是不是对象？
block结构
在apple开源的代码实现中中，可以看到block的结构：
// Values for Block_layout-&gt;flags to describe block objects
enum {
    BLOCK_DEALLOCATI]]></description><category></category></item><item><title><![CDATA[leetCode 2:两数之和]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112246390</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112246390</guid><author>WangErice</author><pubDate>Tue, 05 Jan 2021 19:41:58 +0800</pubDate><description><![CDATA[两数之和分析实现算法复杂度其他算法
给你两个 非空 的链表，表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的，并且每个节点只能存储 一位 数字。
请你将两个数相加，并以相同形式返回一个表示和的链表。
你可以假设除了数字 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 =]]></description><category></category></item><item><title><![CDATA[LeetCode 830: 较大分组的位置]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112220392</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112220392</guid><author>WangErice</author><pubDate>Tue, 05 Jan 2021 16:26:20 +0800</pubDate><description><![CDATA[较大分组的位置分析实现算法复杂度时间优化
在一个由小写字母构成的字符串 s 中，包含由一些连续的相同字符所构成的分组。
例如，在字符串 s = “abbxxxxzyy” 中，就含有 “a”, “bb”, “xxxx”, “z” 和 “yy” 这样的一些分组。
分组可以用区间 [start, end] 表示，其中 start 和 end 分别表示该分组的起始和终止位置的下标。上例中的 “xxxx” 分组用区间表示为 [3,6] 。
我们称所有包含大于或等于三个连续字符的分组为 较大分组 。
找到每一个 较大分]]></description><category></category></item><item><title><![CDATA[LeetCode 509: 斐波那契数]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112188194</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112188194</guid><author>WangErice</author><pubDate>Mon, 04 Jan 2021 22:51:21 +0800</pubDate><description><![CDATA[斐波那契数分析实现算法复杂度时间复杂度空间复杂度其他算法
斐波那契数，通常用 F(n) 表示，形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始，后面的每一项数字都是前面两项数字的和。也就是：
F(0) = 0，F(1) = 1
F(n) = F(n - 1) + F(n - 2)，其中 n &gt; 1
给你 n ，请计算 F(n) 。
示例 1：

输入：2
输出：1

解释：F(2) = F(1) + F(0) = 1 + 0 = 1
示例 2：

输入：3
输出：2

解释：F(3) = F]]></description><category></category></item><item><title><![CDATA[LeetCode 1:两数之和]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112135808</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112135808</guid><author>WangErice</author><pubDate>Mon, 04 Jan 2021 16:32:01 +0800</pubDate><description><![CDATA[两数之和分析实现算法复杂度分析时间复杂度空间复杂度其他算法
给定一个整数数组 nums 和一个整数目标值 target，请你在该数组中找出 和为目标值 的那 两个 整数，并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是，数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
示例 1：

输入：nums = [2,7,11,15], target = 9
输出：[0,1]

解释：因为 nums[0] + nums[1] == 9 ，返回 [0, 1] 。
示例 2：

输入：nums ]]></description><category></category></item><item><title><![CDATA[LeetCode 86:分割链表]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/112135188</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/112135188</guid><author>WangErice</author><pubDate>Sun, 03 Jan 2021 15:37:32 +0800</pubDate><description><![CDATA[分割链表分析实现算法复杂度时间复杂度空间复杂度
给你一个链表和一个特定值 x ，请你对链表进行分隔，使得所有小于 x 的节点都出现在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
示例：

输入：head = 1-&gt;4-&gt;3-&gt;2-&gt;5-&gt;2, x = 3
输出：1-&gt;2-&gt;2-&gt;4-&gt;3-&gt;5

分析
单向链表是一种常用的数据结构，一般会定义个一个值域val和一个指向下一个节点的指针域next,形如：
// Defin]]></description><category></category></item><item><title><![CDATA[算法的时间复杂度]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/111470135</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/111470135</guid><author>WangErice</author><pubDate>Mon, 21 Dec 2020 17:56:21 +0800</pubDate><description><![CDATA[算法的时间复杂度事后统计法估算代码执行次数
对于实现每个开发者都有自己的想法,但并不是每一个算法都会得到很好的应用和推广,受限于运行环境和运行时间的要求，总是会有一些算法虽然也能够得到想要的结果但是终究会被摒弃.而评价一个算法好坏的一个重要标准就是算法的时间复杂度.
对于算时间复杂度，总体上会有两种衡量方法：
事后统计法
对于特性的算法只要使用用例在指定的设备上进行运算就可以获取到算法执行的时间，从而评估算法在执行时间上的优劣.但是这种方法具有明显的缺陷：

执行时间严重依赖于硬件以及运行时各种不确定的环境]]></description><category></category></item><item><title><![CDATA[LeetCode 389]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/111382655</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/111382655</guid><author>WangErice</author><pubDate>Fri, 18 Dec 2020 18:17:47 +0800</pubDate><description><![CDATA[找不同计数法差集法异或位运算
题目描述
给定两个字符串 s 和 t，它们只包含小写字母。
字符串 t 由字符串 s 随机重排，然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。
计数法
因为元素限定了只能是小写字母，是可以枚举的，所以可以使用元素的ascall码作为索引，出现的次数作为索引对应的值来统计元素在s中出现的次数.
char *arr = malloc(sizeof(sizeof(char) * 26));
for (int index = 0; index &lt; strlen(s)]]></description><category></category></item><item><title><![CDATA[正则表达式中的捕获非捕获匹配]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/111352898</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/111352898</guid><author>WangErice</author><pubDate>Fri, 18 Dec 2020 15:58:21 +0800</pubDate><description><![CDATA[正则表达式中的非捕获匹配(?:pattern)(?=pattern)(?!pattern)(?&lt;=pattern)(?&lt;!pattern)
在正则表达之使用中，经常会用到捕获匹配，即使用()进行匹配的分组会被保存在当前的执行环境变量中，从左到右以分组的括号为标志，依次编号为1,2,…,在需要时可以直接使用\1,\2…来进行引用.而在一些匹配场景中其实保存这些变量并没有任何的意义，这时候就需要用到非捕获匹配.
(?:pattern)
(?"pattern)表示一个非捕获分组，和捕获分组比起来，非捕]]></description><category></category></item><item><title><![CDATA[属性语义问题]]></title><link>https://blog.youkuaiyun.com/WangErice/article/details/111315814</link><guid>https://blog.youkuaiyun.com/WangErice/article/details/111315814</guid><author>WangErice</author><pubDate>Thu, 17 Dec 2020 16:53:17 +0800</pubDate><description><![CDATA[属性语义属性的语义特性
属性的语义特性
OC在进行属性声明时可以指定属性的语义特性，语义特性大致可以分为一下几中：


可读属性
可读属性有两个：readonly, rewrite，
默认值:rewrite,可读可写会生成对应的setter和getter方法


原子属性
原子属性有两个：atomic, nonatomic
默认值： atomic,之所以默认值是原子特性，是因为可以保持数据的存取的完整性，而实际开发中多数情况下会使用nonatomic，是因为从性能角度考虑频繁的锁操作会导致执行效率下降.

]]></description><category></category></item></channel></rss>