阿新应对面试

一. 简历知识点

1.熟练掌握多线程的底层实现,线程间的通信以及网络加载时的性能优化

1.1多线程的底层实现
me:

一个应用程序一启动就有一个进程,一个进程至少会有一个线程,这个线程就是主线程,

除了主线程之外我们还可以手动创建其他线程,其他线程我们称为子线程,

一个进程包含多个线程我们称为多线程,

多线程的鼻祖是一个叫Mach的东西,Mach是第一个以多线程方式处理任务的系统,
所以说多线程的底层实现机制是基于Mach的.

但是在开发过程中我们很少用Mach级别的线程,因为Mach级的线程之间是独立,不能进行线程之间的通讯.

所以我们一般都使用GCD NSOperation  NSThread 

POSIX接口这个几乎不用. 用的最多的是GCD,

NSThread也很少用,因为这个管理起来很麻烦,创建,睡眠,等待,阻塞都需要我们自己管理.

所以用的做多的还是GCD和NSOperation, 

这两个再相比较 , 用的最多,当然是GCD,GCD是苹果公司为多核的并行运算提出的解决方案. 
因为GCD是基于XNU内核实现的,iOS OSX的核心就是这个内核.所以它可以直接和内核进行交互,
可以充分利用核,所以性能更高,而其GCD代码更简洁.

而NSOperation是基于GCD的OC的封装,在开发工程中越高级的东西性能就越低,
它需要先转化成GCD再去进行和底层进行交互   多个一个转化的过程.

比如说现在大家都在研究的swift, swift就是对OC的封装,苹果说它比OC的性能好,
但是在底层他还是要转化成OC 再转化成运行时,多个一个转换的过程.
所以有的时候swifit并没有OC性能好.

我记得网上就有大神做个海量的数据测试发现它并没有OC性能高.一般越高级的东西性能越低.

1.2 线程间通信 (未整理)
1.3 网络加载时的性能优化(未整理)

2.熟悉网页与OC之间的交互(未完)

3. 数据存储相关

1.说一说你对SQLite的认识
SQLite是目前主流的嵌入式关系型数据库,其最主要的特点就是轻量级、跨平台.
前很多嵌入式操作系统都将其作为数据库首选。
虽然SQLite是一款轻型数据库,但其功能也绝不亚于很多大型关系数据库。

和其他数据库相比,SQLite中的SQL语法并没有太大的差别

SQLite数据库的有如下几个特点:
1. 它是基于C语言开发的轻型数据库; 在iOS中需要使用C语言语法进行数据库操作、访问
(无法使用ObjC直接访问,因为libqlite3框架基于C语言编写)

2.SQLite中采用的是动态数据类型,即使创建时定义了一种类型,在实际操作时也可以存储其他类型,
但是推荐建库时使用合适的类型(特别是应用需要考虑跨平台的情况时)

3.建立连接后通常不需要关闭连接(尽管可以手动关闭)

在iOS中操作SQLite数据库可以分为以下几步(注意先在项目中导入libsqlite3框架):

打开数据库,利用sqlite3_open()打开数据库会指定一个数据库文件保存路径,
如果文件存在则直接打开,否则创建并打开。

打开数据库会得到一个sqlite3类型的对象,后面需要借助这个对象进行其他操作。

执行SQL语句,执行SQL语句又包括有返回值的语句和无返回值语句。
对于无返回值的语句(如增加、删除、修改等)直接通过sqlite3_exec()函数执行;
对于有返回值的语句则首先通过sqlite3_prepare_v2()进行sql语句评估(语法检测),
然后通过sqlite3_step()依次取出查询结果的每一行数据,对于每行数据都可以通过对应的
sqlite3_column_类型()方法获得对应列的数据,如此反复循环直到遍历完成。当然,最后需要释放句柄。

2.SQLite 数据存储是怎么用?

• 添加SQLite动态库
• 导入主头文件:#import
• 利用C语言函数创建打开数据库,编写SQL语句

- me: 

   - 添加SQLite动态库: libsqlite3.0.tbd
   - 导入主头文件 : #import <sqlite3.h>
   - 准备数据库存储的路径
   - 创建数据库文件并打开 (使用sqlite3_open函数)    
   - 判断数据库是否创建打开成功  (result == SQLITE_OK)
      - 如果创建数据库文件成功,就创建数据库表
      - 创建数据库表成功就可以操作数据库 (增删改查)

(提示: 1.建表和数据操作函数(查询函数除外) : sqlite3_exec       me:建表,增,删,改 /ɪg'zek/
       2.查询函数 : sqlite3_prepare_v2
      3.查询数据时会得到结果集,要查询的数据都在结果集中,while循环遍历结果集一条一条记录取出来
 )

3.说一说你对FMDB的认识 (待捋顺)
FMDB是一个处理数据存储的第三方框架,框架是对sqlite的封装,整个框架非常轻量级但又不失灵活性,
而且更加面向对象。
  
FMDB有如下几个特性:
    
FMDB既然是对于libsqlite3框架的封装,自然使用起来也是类似的,使用前也要打开一个数据库,
这个数据库文件存在则直接打开否则会创建并打开。

这里FMDB引入了一个MFDatabase对象来表示数据库,打开数据库和后面的数据库操作全部依赖此对象。

对于数据库的操作跟前面KCDbManager的封装是类似的,
在FMDB中FMDatabase类提供了两个方法executeUpdate:和executeQuery:
分别用于执行无返回结果的查询和有返回结果的查询。
如果调用有格式化参数的sql语句时,格式化符号使用“?”而不是“%@”、等。

我们知道直接使用libsqlite3进行数据库操作其实是线程不安全的,如果遇到多个线程同时操作一个表的时候可能会发生意想不到的结果。

为了解决线程不安全的问题, 建议在多线程中使用FMDatabaseQueue对象,相比FMDatabase而言,它是线程安全的。

将事务放到FMDB中去说并不是因为只有FMDB才支持事务,而是因为FMDB将其封装成了几个方法来调用,
不用自己写对应的sql而已。其实在在使用libsqlite3操作数据库时也是原生支持事务的
(因为这里的事务是基于数据库的,FMDB还是使用的SQLite数据库),只要在执行sql语句前加上“begin transaction;
”执行完之后执行“commit transaction;”或者“rollback transaction;”进行提交或回滚即可。

另外在Core Data中大家也可以发现,所有的增、删、改操作之后必须调用上下文的保存方法,
其实本身就提供了事务的支持,只要不调用保存方法,之前所有的操作是不会提交的。

在FMDB中FMDatabase有beginTransaction、commit、rollback三个方法进行开启事务、提交事务和回滚事务。
4.说一说你对Core Data的认识
Core Data使用起来相对直接使用SQLite3的API而言更加的面向对象,

操作过程通常分为以下几个步骤:

- 创建管理上下文
创建管理上下可以细分为:加载模型文件->指定数据存储路径->创建对应数据类型的存储->创建管理对象上下方并指定存储。
经过这几个步骤之后可以得到管理对象上下文NSManagedObjectContext,以后所有的数据操作都由此对象负责。
同时如果是第一次创建上下文,Core Data会自动创建存储文件(例如这里使用SQLite3存储),
并且根据模型对象创建对应的表结构。

- 查询数据
对于有条件的查询,在Core Data中是通过谓词来实现的。
首先创建一个请求,然后设置请求条件,最后调用上下文执行请求的方法。

- 插入数据
插入数据需要调用实体描述对象NSEntityDescription返回一个实体对象,然后设置对象属性,最后保存当前上下文即可。
这里需要注意,增、删、改操作完最后必须调用管理对象上下文的保存方法,否则操作不会执行。

- 删除数据
删除数据可以直接调用管理对象上下文的deleteObject方法,删除完保存上下文即可。
注意,删除数据前必须先查询到对应对象。

- 修改数据
修改数据首先也是取出对应的实体对象,然后通过修改对象的属性,最后保存上下文。


5、如果后期需要增加数据库中的字段怎么实现的,如果不使用 CoreData 呢?
编写SQL语句来操作原来表中的字段

• 增加表字段
  ALTER TABLE 表名 ADD COLUMN 字段名 字段类型;     ----- me: alter table 表名 add column 字段名  字段类型;
• 删除表字段
  ALTER TABLE 表名 DROP COLUMN 字段名;    -----me: alter table 表名 drop column 字段名;
• 修改表字段
  ALTER TABLE 表名 RENAME COLUMN 旧字段名 TO 新字段名   -----me: alter table 表名 rename column 旧字段名 to 新字段名

alter/'ɔːltə/ 改变,修改 column /'kɑləm/ 列

6.你实现过多线程的 Core Data 么? NSPersistentStoreCoordinator , NSManagedObjectContext 和 NSManagedObject 中的哪些需要在线程中创建或者传递?你是用什 么样的策略来实现的?
1. CoreData是对SQLite数据库的封装 

2. CoreData中的NSManagedObjectContext在多线程中不安全 

3.如果想要多线程访问CoreData的话,最好的方法是一个线程一个NSManagedObjectContext 

4.每个NSManagedObjectContext对象实例都可以使用同一个NSPersistentStoreCoordinator实例,
这是因为 NSManagedObjectContext会在使用NSPersistentStoreCoordinator 前上锁

/pə'sɪst(ə)nt/持续的,不断的 /kəʊˈɔ:dɪneɪtə/ 协调者

7.简单描述下客户端的缓存机制?
缓存可以分为:内存数据缓存、数据库缓存、文件缓存 

每次想获取数据的时候-->先检测内存中有无缓存 -->再检测本地有无缓存(数据库文件)

--->最终发送网络请求

--->将服务器返回的网络数据进行缓存(内存、数据库、文件), 以便下次读取

8.说说数据库的左连接和右连接的区别,如果有A,B两张表,A表有3条数据,B表有4条数据,通过左连接和右连接,查询出的数据条数最少是多少条?最多是多少条?
  • 数据库左连接和右连接的区别:主表不一样
  • 通过左连接和右连接,最小条数为3(记录条数较小的记录数),最大条数为12(3×4)
(1)左连接:只要左边表中有记录,数据就能检索出来,而右边有的记录必要在左边表中有的记录才能被检索出来

(2)右连接:右连接是只要右边表中有记录,数据就能检索出来

9.说一下应用(Bundle)包和沙盒?__ljx自我自答
- bundle: 存放的是"应用的可执行文件及其资源图片"等,
     (比如 Info.plist: 此文件包含了应用程序的配置信息. 系统依赖此文件以获取应用程序的相关信息       
           可执行文件 : 此文件包含应用程序的入口和通过静态连接到应用程序target的代码
             资源文件 : 图片,声音文件一类的
                其他 : 可以嵌入定制的数据资源  )
          通过[NSBundle mainBundle].bundlePath 可以获取到应用的包路径;
       
- 沙盒: 沙盒目录可以用来进行数据存储和读取操作!
       (注意:一个应用不允许访问其他应用的沙盒目录,只能在自己的沙盒中进行操作!)
       沙盒的路径会变,但是只要通过NSHomeDirectory就一定能获取到当前程序的沙盒根目录.
      
      
       应用的沙盒根目录,默认有Document/Library/temp三个子目录,  
      
      - Document是文档目录,可以用于存储一些比较重要的数据,由应用程序生成的数据!
       在备份的时候,会备份此目录!这里不能存缓存文件,否则上架不被通过
        获取文档目录: [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
       
      - Library中有2个子目录,分别是 Caches和Preferences    
       
         Caches /kæʃ/ 是 缓存目录,通常保存从网络上下载的需要持久化的数据
          在备份时,不会备份该目录,并且不会自动删除数据,需要程序内部提供删除的操作!
         
         Preferences /'prɛfrəns/ 专门用来存储'偏好设置'相关的数据', 在偏好设置存储时使用,
         偏好设置存储的本质是以字典的形式将数据写入plist文件中,   用来快速存储键值对
           ● 不需要指定文件名(默认为 bundleid + .plist) 和 路径
           ● 关键类:NSUserDefaults   
         - 在存储数据时,首先需要获取偏好设置对象 , 存储数据,需要设置数据对应的key!
         在iOS7.0之前,是以定时的形式保存的, 要想保证数据立即被写入磁盘,当时还要写同步操作
         即要调用这个对象的synchronize的方法,iOS7.0之后就不用了
         - 在读取数据时, 同样需要获取偏好设置对象,根据key读取数据
    
    /* 存储数据 */     
    // 1.1 获取偏好设置对象
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  /'stændəd/ 
    NSString *name = @"zhangsan";
    // 1.2 存储数据
    [defaults setObject:name forKey:@"NAME"];
    // 1.3 同步
   //[defaults synchronize];
   
   /* 读取数据 */
    NSString *str = [defaults objectForKey:@"NAME"];
    NSLog(@"%@", str);

       
      - temp /temp/ 临时目录.
        用来保存临时数据,可能在内存紧张的时候会随时被干掉,itunes不会备份
     
12.你知道哪些数据存储方式__ljx自我自答 (未完)
  • plist存储 :系统提供的字典数据等可以直接通过writeToFile:的方式写入文件

    • 使用简单,方便 ; 是偏好设置存储的基础!
  • 偏好设置存储 :

    • 01-系统提供的API方便高效!
    • 02-程序员不需要管 存储的路径及文件等信息,统一由系统负责
    • 03-偏好设置存储的本质是以字典的形式将数据写入plist文件中

      • 在存储数据时,首先需要获取偏好设置对象 , 存储数据,需要设置数据对应的key! 在iOS7.0之前,是以定时的形式保存的, 要想保证数据立即被写入磁盘,当时还要写同步操作 即要调用这个对象的synchronize的方法,iOS7.0之后就不用了
      • 在读取数据时, 同样需要获取偏好设置对象,根据key读取数据
  • 归档&解档 : 专门用来保存自定义对象; (保存自定义对象的过程叫做归档,读取自定义对象的过程叫做解档)

    • 归档:关键类:NSKeyedArchiver /kid/ /'ɑ:kaiv/ NS kid 啊开哇
    • 解档:关键类:NSKeyedUnarchiver

    • 用法

 - 需要遵守NSCoding协议  <NSCoding>
              - 实现协议方法
                // 归档调用 存储    --告诉系统需要归档哪些属性,怎么去存,存哪些
                 - (void)encodeWithCoder:(NSCoder *)encoder
               //  解档调用 读取      --告诉系统需要解档哪些属性,怎么去取,取哪些
                 - (instancetype)initWithCoder:(NSCoder *)decoder
10.iOS 的沙盒目录结构是怎样的? App Bundle 里面都有什么?
  • 沙盒结构

    • Application:存放程序源文件,上架前经过数字签名,上架后不可修改
    • Documents:常用目录,iCloud备份目录,存放数据,这里不能存缓存文件,否则上架不被通过 Library
    • Caches:存放体积大又不需要备份的数据,SDWebImage缓存路径就是这个
    • Preference:设置目录,iCloud会备份设置信息
    • tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能
  • App Bundle 里面有什么

me: Bundle里面主要存放,应用的可执行文件及其资源图片等

细说:
Info.plist: 此文件包含了应用程序的配置信息.系统依赖此文件以获取应用程序的相关信息
可执行文件: 此文件包含应用程序的入口和通过静态连接到应用程序target的代码
资源文件: 图片,声音文件一类的
其他: 可以嵌入定制的数据资源
10.core data数据迁移
11.FMDB 的使用和对多张表的处理
FMDB
  • FMDB:

    • 是iOS平台的SQLite数据库框架
    • 以OC的方式封装了SQLite的C语言API
  • FMDB的优点:

    • 使用起来更加面向对象,省去了很多麻烦,冗余的C语言代码
    • 对比苹果自带的Core Data框架,更加轻量级和灵活
    • 提供了多线程安全的数据库操作方法,有效地防止数据混乱
  • (待修改)我的应用使用场景: 离线缓存

    • 加载"内涵笑话"过程
      1.尝试从沙盒加载缓存数据
      • 有缓存-->直接加载缓存
      • 无缓存-->发送网络请求-->展示返回的数据-->将数据存入到沙盒
    • 需要加载的"内涵笑话"多,数据量大,不适合用plist和NSCoding这类一次性加载和存储全部数据的方法,使用数据库则可以做到取一部分数据和存一部分的数据
相关知识点
事务
  • 使用场景:大规模数据操作时使用
  • 我的理解:
    用于解决数据库中执行多条SQL语句时,想让多条语句要么一起成功要么一起失败.

  • 使用步骤:
    1.在准备做大规模数据操作前,首先开启一个事务,保证操作前数据库的状态(快照)
    2.开始数据操作
    3.如果数据操作成功,提交事务,让数据库更新到数据操作后的状态
    4.如果数据操作失败,回滚事务,让数据库还原操作前的状态.

  • 事务 SQL

    • 开启事务 BEGIN TRANSACTION ----- me: begin transaction;
    • 提交事务 COMMIT TRANSACTION ----- me: commit transaction;
    • 回滚事务 ROLLBACK TRANSACTION ----- me: rollback transaction;
  • 事务的特性

    • 原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
也就是说一个事务执行之前和执行之后都必须处于一致性状态。
例子1: 
 拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
例子2:要求A+B = 10 ,A B 两个变量必须一致,A=1 ,B一定要等于9,A=2,B一定要等于8.
事务前后,数据库的状态都满足所有的完整性约束。
博客2:
只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初的状态。
事务需要保持数据库的正确性、完整性和一致性。
有些时候这种一致性由数据库的内部规则保证,例如数据的类型必须正确,数据值必须在规定的范围内,等等。
另外一些时候这种一致性由应用保证的,例如, 一般情况下银行账务余额不能是负数,信用卡消费不能超过该卡的信用额度等。


隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的
其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
比如:操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改
变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
me: 在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
  • 如果没有显式的开启事务,SQLite会:

    • 在每一次数据库操作前开启事务(非常影响数据库的性能)
    • 操作完成,自动提交事务;
    • 性能差!!!
  • 使用事务可以:

    • 数据库操作之前,建立快照
    • 数据库操作完成之后,提交快照
    • 提高数据操作性能
    • 保证数据完整性
其他

SQL的查询语句

  • 常用用的查询语句
    • ● 排序查询语句 (order by默认就是从小到大排序, desc 是从高到低排序;)
    • ● 分页查询语句 (limit可以精确地控制查询结果的数量)
    • ● 模糊查询语句 (like 使用场景 : 关键字搜索)

eg: 查询商品价格信息包含99的所有商品,并且价格小于5000,按照价格从高到低排序,取前面5条记录
select * from t_product where productPrice like'%99%' and productPrice < 5000 order by productPrice desc limit 0,5;

查询语句的顺序大概如下:
select * from 表名 条件语句 模糊查询 排序语句 分页语句

1.熟练使用CocoPods管理第三方类库

1.1CocoPods的底层原理
CocoaPods是iOS项目的依赖管理工具,该项目源码在Github上管理。

在使用CocoaPods之前,需要用到第三方开源库的时候,我们需要
1.把开源库的源代码复制到项目中
2.添加一些依赖框架和动态库
3.设置-ObjC,-fno-objc-arc等参数
4.管理他们的更新

在使用CocoaPods后,只需要把用到的开源库放到一个名为Podfile的文件中,
然后执行pod install.    Cocoapods就会自动将这些第三方开源库的源码下载下来,
并且为我们的工程设置好响应的系统依赖和编译参数。

CocoaPods的原理是将所有的依赖库都放到另一个名为Pods的项目中,然后让主项目依赖Pods项目,
这样源码管理工作都从主项目移到了Pods项目中。Pods项目最终会编译成一个名为libPods.a的文件,
主项目只需要依赖这个.a文件即可。

  • 库文件引入及配置:
    库文件的引入主要由Pods工程中的 Pods-项目名-frameworks.sh 脚本负责,在每次编译的时候,
    该脚本会帮你把预引入的所有三方库文件打包的成 项目名.a 静态库文件,放在我们原Xcode工程中Framework文件夹下,供工程使用。

  • Resource文件:
    Resource资源文件主要由Pods工程中的Pods-项目名-resources.sh脚本负责,在每次编译的时候,该脚本会帮你将所有三方库的Resource文件copy到目标目录中。

  • 依赖参数设置:
    在Pods工程中的的每个库文件都有一个相应的SDKName.xcconfig,在编译时,CocoaPods就是通过这些文件来设置所有的依赖参数的,编译后,在主工程的Pods文件夹下会生成两个配置文件,Pods-项目名.debug.xcconfig、Pods-项目名.release.xcconfig。 /rɪ'lis/

在一些工程中pod是如何集成到项目中的?
常用的第三方框架
  • 1.1 AFNetWorking

  • 1.2 SDWebImage

  • 1.3 YYWebImage

  • 1.4 GPUImage

  • 1.5 MJRefresh

  • 1.6 Masonry/SnapKit

添加自动布局约束有以下几种方式:
  1.使用Xcode的Interface Builder界面设计器添加并设置约束
  2.通过系统原生的NSLayoutConstraint逐条添加约束
  3.通过可视化格式语言VFL添加约束
  4.使用第三方类库(如Masonry)添加约束
  
  
Masonry :  
   - 对系统NSLayoutConstraint进行封装的第三方自动布局框架,
    
   - 采用链式编程的方式提供给开发者API。
    
   - Masonry是同时支持Mac和iOS两个平台的. 我们可以从MASUtilities.h文件中,
    看到下面的定义,这就是Masonry通过宏定义的方式,区分两个平台独有的一些关键字。
   
   - 要在addSubview之后才能使用,否则会导致崩溃。
     
   - 约束出现问题的原因一般就是两种:约束冲突和缺少约束。   对于这两种问题,可以通过调试和log排查。
      之前使用Interface Builder添加约束,如果约束有错误直接就可以看出来,
      并且会以红色或者黄色警告体现出来。
      
      而Masonry则不会直观的体现出来,而是以运行过程中崩溃或者打印异常log体现,
      所以这也是手写代码进行AutoLayout的一个缺点。
  
  
   eg:   make.edges.offset(0); //四边0边距
         make.height.offset(180);  //设置高
         make.left.top.right.offset(0);//相对父控件左上右0间距
         .....
   - 给UIScrollView(滚动视图)中的直接子控件添加约束比较特殊 上下左右+宽+高       


    
  • 1.7 MasMBProgressHUD / SVProgressHUD,
  • 1.8 MMDrawerController
  • 1.9 POP
  • 1.10 YYModel/MJExtension
  • 1.11 SSZipArchive
  • 1.12 FMDataBase
  • 1.13 GData
  • 1.14 YYKit
  • 1.15 FMDB
  • 1.16 友盟

UI

(不全)曾了解过的约束方法进行屏幕适配__ljx自问自答
  • 将来显示后图片的高 = 将来显示后图片的宽 * 图片的真实高 / 图片真实宽 make.height.equalTo(pictureView.mas_width).multipliedBy(pictureView.bounds.size.height / pictureView.bounds.size.width);
其他
  • 自定义样式的按钮文字默认是18 ,系统样式的是15 ;

数据结构算法篇

http://blog.csdn.net/yangshebing21/article/details/51292477
需要掌握的知识:

反转链表
二分查找法
冒泡排序
二分法
数据结构(链表、二叉树、算法时间复杂度、空间复杂度)
什么是二叉搜索树?时间复杂度是什么?
采用二叉树链表作为存储结构,每个左节点均小于父节点,每个右节点均大于父节
点
O(log2(n))
T9 算法如何实现, 全拼算法
最短路径算法
强连通量算法
实现连连看算法
如何实现一个数组每个元素依次向右移动 k 位。(后头的往前面补) 比如: [1, 2, 3, 4, 5] 挪两位变成[4, 5, 1, 2, 3]
求两个整数的最大公约数
微信用户都是双向的好友,a 是 b 的好友,那么 b 一定是 a 的。给定一个用户列表, 有些用户是好友,有些不是,请判断,这些用户是否可以划分为两组,每组内的用 户, 互相都不是好友。如果能,请给出这个划分
算法题:说 预约会议室,会有 n 个团队预约当天会议室,时间各不相同,求最少 需要几个会议室。比如:1 预约的时间是[9-11], 2 预约的时间是[10-12], 3 预约的时 间是[12-14], 此时会议最小个数是 2 个

选择排序

1.什么是选择排序
选择排序即:分别拿到数组中的第i个元素,依次跟第i+1到第len -1 的元素进行比较,
满足条件则交换比较的两个数,否则,什么都不做

2.如何代码实现 - 思路
1>要分别拿到数组中的第i个元素,需要循环遍历数组
2>当拿到数组中第i个元素时,要依次跟第i+1到len - 1的元素进行比较,
需要再写一个循环遍历第i+1到len-1的元素
即:两个循环 -> 且循环嵌套
3>满足条件时,交换当前比较的两个数

int main()
{
    int arr[] = {1,2,4,3,8,5};
    int len=sizeof(arr)/sizeof(arr[0]);

    for (int i = 0; i < len-1; i++)//控制多少轮
    {
        for (int j = i + 1 ; j < 6; j++)//每一轮具体实现
        {
            if(arr[j]>arr[i])
            {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        
    }
    return 0;
}

冒泡排序

  • 1.什么是冒泡排序
    冒泡排序即:对要排序的数组进行多轮遍历,每一轮遍历拿数组中相邻的两个元素进行比较,满足条件则交换。否则,什么也不做

  • 2.冒泡排序代码实现 - 思路
    1>首先要确定遍历多少轮,每一轮的遍历都会将数组中的一个元素排好序并冒到最后面,
    所以遍历len - 1轮即可,因为5个元素,每次都是从第1个元素比较的,当把后4个元素排好时,
    剩下的1一个元素自动就排好序了

2>每轮排序都会确定一个数,所以第i轮需要比较len - i - 1此, 且从0到len - i - 1两两比较。
i后面的元素已经排好序了。 "注意,遍历元素比较时会将当前元素下标加1去拿到相邻下一个元素,
y一定注意从0到len - i - 1,否则会拿到垃圾值

即:需要两个循环 -> 且循环嵌套
    外层循环 控制遍历轮数
    内层循环 控制比较次数

3>满足条件时,交换当前比较的两个数

int main()
{
    
    int arr[] = {1,2,4,3,8,5};
    int len=sizeof(arr)/sizeof(arr[0]);
    int temp;
    for (int i = 0; i < len-1; i++)//要进行多少轮
    {
        for (int j = 0; j < len - i - 1; j++)//每一轮具体的实现
        {
            if(arr[j] < arr[j+1])
            {
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                
            }
        }
    }

    return 0;
}

二分查找法

  • 1.什么是二分查找?
    拿要查找的数组中间的数比较,因为数组有序,可通过比较结果一步步缩小搜索范围,直到找到

  • 2.二分查找代码实现 -思路

    1>循环比较拿查找的数和中间数进行比较 -> while(key != arr[mid])

    2>根据比较结果改变min max 及 mid 值
    int min = 0;
    int max = len - 1;
    int mid = len / 2; //初始值

    "注意:当min > max 时结束循环,说明没找到

int main()
{
    int arr[] = {10,45,67,89,90,99,122,456,789,999};
    int min = 0;
    int max = sizeof arr / sizeof arr[0] - 1;
    int mid = (min + max)/2;
    
    while (arr[mid]!= 789) {  //只要没有找到就进入循环继续寻找
        
        if(arr[mid] < 789)
        {
            min = mid + 1;
        }
        
        if(arr[mid] > 789)
        {
            max = mid - 1;
        }
    }
    
    printf("%d
",mid);
}

HTTPS

● HTTPS : Hyper Text Transfer Protocol over Secure Socket Layer,
是以安全为目标的HTTP通道,简单讲是HTTP的安全版.
即HTTP下加入SSL层,HTTPS的安全基础是SSL.
● SSL : Secure Sockets Layer,表示安全套接层.
● TLS : Transport Layer Security,是SSL的继任者,表示传输层安全.
● SSL与TLS是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密.
HTTPS协议比HTTP协议的效率要低些.

me:
HTTPS下:
SSL 和TSL 只是加密的地方不一样 ,其他都是类似的
SSL 是在Socket层加密
TSL 是在传输层加密 

HTTPS和HTTP区别

HTTPS加密原理


  • HTTPS加密原理

    • 加密算法: 对称加密算法 (加密和解密使用相同的钥匙) --->密钥最重要(公钥加密,私钥解密)
    • 大白话:

      • 1.发送https协议的网络请求 (访问服务器中花钱购买的证书-钥匙(私钥和公钥))
      • 2.获取公钥和私钥
      • 3.把公钥发送到客户端
      • 4.客户端获取公钥 --- 然后验证公钥是否合法(/是否花钱)

        • 证书有效时-->提醒用户访问的是非安全链接
        • 证书有效时-->生成随机数key (就是对称加密的钥匙)
        • 使用公钥对生成的随机数key进行加密
      • 5.把加密后的key 传输到服务器

      • 6.服务器拿到加密后的key,使用私钥进行解密.

      • 7.服务器也可以加密和解密,如果服务器向客户端传输数据时,服务器使用key给数据加密

      • 8.客户端收到数据后使用key给其解密就ok了

      • 9.如果客户端要给服务器数据,咋同样客户端使用key加密,服务器收到后使用key解密.

me : https使用对称加密算法加密数据,使用非对称加密算法加密它的密钥    
加密相关 (未整理啦啦啦啦)
  • 对称加密算法: 加密和解密使用相同的钥匙.(顾:钥匙的安全性最重要,注意定期的更换密钥)

    • DES / 3DES / AES
  • 非对称加密算法: 密钥A加密, 密钥B解密 ; 密钥B加密 ,密钥A解密

    • RSA
AES / RSA
MD5加密--(信息-摘要算法) 哈希算法之一
- 是不可逆的加密,只能加不能解     (中国密码专家 王小云已经把MD5算法破解了)

二.其他

1. 你在实际开发中,有哪些手机架构与性能调试经验(待优化)
1.刚接手公司的旧项目时,模块特别多,而且几乎所有的代码都写在控制器里面,
比如UI控件代码、网络请求代码、数据存储代码

2.接下来采取MVC模式进行封装、重构 • 自定义UI控件封装内部的业务逻辑
• 封装网络请求工具类
• 封装数据存储工具类

比如:封装网络请求工具类

me: 
1. 创建一个继承自AFHTTPSessionManager 网络的管理者,我将其定义成了单例设计模式.
2. 设置全局访问点,然后去写实现代码.
     在实例化单例对象是同时时, 封装相对路径baseURL--(我们app的域名基本上都是一个,
     在封装网络请求工具类的时候,把baseURL封装出来,将来发送网络   请求时只需要路径就可以)
     还要注意把id类型,改为你创建的类名
    
     增加AFN支持的文件类型

2. 封装GET请求---(注意其中的Block回调时,一定要判断是否为空,一旦为空,如果强制调用,就会空指针访问)


原文地址:https://www.cnblogs.com/ljx-xinge/p/a-xin-ying-dui-mian-shi.html