算法相关 iOS 面试题算 简单的
经典排序算法好文- 链接
iOS面试·一个iOS程序员的BAT面试全记录(内含百度+网易+阿里面试真题)
文中反馈很多是剑指offer 的题目
github 常用的算法题 /iOS-Interview/blob/master/常用算法面试题.md
排序+基本二叉树
iOS面试题系列之常见算法
排序 + 二分
iOS面试常见算法题2020(一)
简单递归 + 字符串
维他命总结的算法题
简单数学问题, 数组,排序,字符串,基本二叉树
IOS面试题之算法基础2
字节的算法 23、编程题:实现一个二叉树的倒置。 2、青蛙跳格子,斐波拉契数列;青蛙跳格子,斐波拉契数列; 1、 算法题:求只有三项元素的数组中的顺序排列,时间复杂度要求O(n);
面试题 常考的算法
排序 链表 搜索 字符串 其他
里面有算法
排序爬楼梯 数组
wg算法总结
- A帮 算法 最大的N个数
- PP公司 , 二分查找 + 括号匹配 , 单链表和双链表的区别
- C公司 有序数组去重
同事面试总结
面试核心还是项目>工程&八股,大家可以类似出这样的知识图谱针对性复习下@稀土掘金技术社区
多线程看代码结果 , 串行中嵌套并行, 并行嵌套同步异步, 互相签到
别的大佬总结的婷婷说差不多 之前至少要刷下《剑指offer》上的所有题目,这本书上的题目都是经典中的经典,面试出现概率极高。有时间的话可以刷下LeetCode上easy和medium难度的题,iOS面试,很少有考察hard的题目,但是就算是遇到h ard的题目也不要过于紧张,仔细审题,寻找突破口。算法是一个积累的过程,现在LeetCode可以每日打卡,这是一个很好的积累手段。下面罗列下常考的数据结构和算法:
数据结构
- 数组
- 链表
- 树
- 算法
二分(就本人经验来看出现概率极高)。
- 分治
- 排序(8大排序)
- 树的遍历(前、中,后)
- BFS以及DFS @稀土掘金技术社区
- DP(出现概率较低)
同事面试遇到的算法
- 百度:写遍历子视图打印 然后我写了一个递归的深层遍历.他就说让我再用层次遍历写一个
- 给你一个链表 然后给你一个左右区间 然后把这个区间里面的链表翻转
- 字节:写的是自己实现一下字典转字符串
- 彼此
- 我刚才面得字节 然后写的是自己实现一下字典转字符串
- 删除链表的倒数第 N 个结点
- 一般算法题 链表可能就是问你怎么找环
- weip和作业b的面试题是 找数组第K大的数
- 找最长的公共字符串
- 字典转字符串是key和value转化为字符串?
- 遍历+拼接?我昨天写的是给你一个链表然后给你一个左右区间然后把这个区间里面的链表翻转 反转
考核形式
- 一般让你用自己编译器写的 会让你运行 ,对的 少数运行
- 写的是伪代码 大致逻辑对 就可以
- 我今天面得weip 就让我跑了
- 然后他那个面试的编译器 没有提示
- 问问题 然后看代码 问你这代码有啥问题不
- 皮皮询问:有优化空间吗?
- 校招考过树, 社招一般是链表 ,社招没遇到链表和图
- 社招一般我感觉好像都是链表呢
- 但是树 图啥的目前我还没遇到考过.我只有在校招的时候 遇到考过树
一) 冒泡排序
guard 的好处
使用 guard
的方式来解包可选值是非常推荐的。if let
的方式需要在大括号内使用解包之后的值,而 guard
语句将解包之后的值添加到了之后的作用域之中——所以你可以在使用 guard
解包之后直接使用它,不用包裹在大括号内。
我们更推荐使用 guard
的方式,因为如果你有多个需要解包的可选值,使用 guard
的方式可以避免金字塔灾难(多个层级的 if let
嵌套)
对我们的大脑来说,在简单的情况下,理解一个扁平的代码路径相比于理解分析嵌套的分支结构更为容易。
步骤如下:
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个,直到把最大的元素放到数组尾部。
-
遍历长度减一,对剩下的元素从头重复以上的步骤。
-
直到没有任何一对数字需要比较时完成。
func bubbleSort() {
var arr = [1,5,2,3,4,8,10];
for i in 0..<arr.count {
for j in i+1..<arr.count {
if arr[j] > arr[i] {
let temp = arr[j]
arr[j] = arr[i]
arr[i] = temp
}
}
}
print("结果\(arr)")
}
bubbleSort()
二) 选择最小值交换
// 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
func selectSort() {
var arr = [2,3,7,9,1,2,3,5];
for i in 0..<arr.count {
var min = i;
for j in i+1..<arr.count {
if arr[j] < arr[min] {
min = j
}
}
let temp = arr[i]
arr[i] = arr[min]
arr[min] = temp
}
print(arr)
}
selectSort()
步骤如下: * 从第一个元素开始,该元素可以认为已经被排序 * 取出下一个元素,在已经排序的元素序列中从后向前扫描 * 如果该元素(已排序)大于新元素,将该元素移到下一位置 * 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置 * 将新元素插入到该位置后 * 重复步骤2~5
作者:jackyshan
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三) 插入排序
func insertSort() {
var arr = [5,4,3,2];
for i in 1..<arr.count {
var y = i // 1,2,
while y > 0 && arr[y] < arr[y-1] {// y = 1 ,a[1] > a[0] // y = 2 ,
let temp = arr[y]
arr[y] = arr[y-1]
arr[y-1] = temp
y -= 1
}
}
print(arr)
}
insertSort()
var myString = "Hello world! - swift.jsrun.net"
print(myString)
四) 快速排序
func quickSort<T: Comparable>(_ a:[T]) -> [T] {
if a.count == 0 {
return a
}
let mid = a.count / 2
let less = a.filter { $0 < a[mid] }
let more = a.filter { $0 > a[mid] }
let equal = a.filter {$0 == a[mid]}
return quickSort(less) + equal + quickSort(more)
}
print(quickSort([1,3,5,7,2,3,8]))
func quickSort(_ nums:[Int]) -> [Int] {
var nums = nums
return quickSortInner(&nums,0,nums.count - 1)
}
iOS可视化动态绘制八种排序过程(Swift版)
前面几篇博客都是关于排序的,在之前陆陆续续发布的博客中,我们先后介绍了冒泡排序、选择排序、插入排序、希尔排序、堆排序、归并排序以及快速排序。俗话说的好,做事儿要善始善终,本篇博客就算是对之前那几篇博客的总结了。而本篇博客的示例Demo也是在之前那些博客Demo的基础上做的,也算是集成了各种排序的方法,然后给出了可视化的解决方案。今天博客的内容还是比较有趣的。
因为本猿是做iOS开发的,所以就使用iOS相关的组件来表示上述各种排序的过程。使用可视化方式来感受一下上述这些排序方法的异同。本篇博客所使用的相关的排序代码都是来自于之前的博客。因为我们在之前实现各种排序Demo时,我们定义了相应的排序接口SortType,所以上述的七种排序对外的调用方式是一致的,所以在此基础上给出相应排序的可视化解决方案并不困难。本篇博客就会给出其相应的扩展过程。
如果你想对上述7中排序进行详细的了解,请移步与之前的博客《冒泡排序、插入排序、希尔排序、选择排序》、《堆排序》、《归并排序》、《快速排序》、《基数排序》。废话少说,开始今天的博客。
一、可视化解决方案综述
1.交互UI综述
在本篇博客的第一部分我们先来整体的看一下我们Demo的功能。下方就是我们今天博客中的Demo的交互示意图。上方的输入框可以输入要排序元素的个数,下方输入的是300。程序会根据你输入的个数来随机生成数据,你输入300,就会随机生成300个数据提供排序使用。下方的SegmentControl可以选择不同的排序方式,本篇博客给出了7中常用的排序方式,选择完排序方式后可以点击右上方的排序按钮进行相应的排序。
下方显示的不同颜色的颜色条就是我们要排序的东西,我们会按照从小到大的方式对这些色条进行排序。左图中是未排序的状态,右图中是已经排序的状态。我们上面随机生成的数据反应到色条上就是色条的高度,我们按照色条的高度进行从小到大的排序。下方会给出每种排序的介绍。
2、部分核心代码实现
为了实现今天的Demo,我们需要对之前我们实现的那一些列的排序的方法进行扩展。因为我们之前在实现各种排序时,我们先定义了SortType接口,依据“开放封闭原则”,我们可以为各种排序的类创建一个“简单工厂”以供我们的视图层使用。关于设计模式更多以及更详细的内容,可以移步之前发布的设计模式系列博客《设计模式Swift版》。
上方就是为各种Sort类提供的“简单工厂”。上面这个简单工厂在视图控制器中点击SegmentControl时会使用,因为我们在选择不同排序类的时候需要使用不同的排序对象。下方就是我们视图控制器对“简单工厂”的调用,当然我们所有排序类都有父类,你也可以使用“工厂方法”来创建相应的对象,在此就不做过多赘述了。
下方代码段就是点击SegmentControl要调用的方法,其中从“简单工厂”中获取到相应排序方式的对象后,然后在设置相应的闭包回调。
二、冒泡排序
接下来我们来逐一看一下每种排序的具体效果。下方就是冒泡排序的效果,因为冒泡排序的时间复杂度是O(n^2)的,所以我们先设置元素个数是80, 如果太大的话会比较慢。因为我们在排序步骤结果输出时,每进行一次交换操作或者比较操作让排序线程休眠0.001秒,便于我们观察整个排序过程。
从下方这个动图上我们不难看出冒泡的整个过程,较小的数据从右往左以此往外冒。下方这个效果还是比较直观的,整个冒泡过程就是从后往前比较,如果后边的数要比前边的小就交换。冒泡过程如下所示:
三、选择排序
选择排序的时间复杂度也是O(n^2)。下方是“选择排序”的可视化过程,选择排序的过程就是从无序序列中找出最小的那个值放到有序序列中最后方。不断执行这个过程,我们的序列就是有序的了。下方就是选择排序的整个过程,元素的个数是80.
四、插入排序
插入排序的复杂度与上述选择排序的时间复杂度一样,都是O(n^2)。下方就是插入排序的运行结果。插入排序是从无序序列中取出第一个值,然后插入到前方有序序列中相应的位置。每次插入后,有序序列就会增加1,无序序列就会减少1。下方就是插入排序的过程,如下所示:
五、希尔排序
希尔排序的效率要高一些,其时间复杂度是O(n^(3/2))。下方就是希尔排序的具体执行步骤,希尔排序又称为缩小增量排序。该排序方式是插入排序的升级版,等增量缩小到1时,我们的序列就是有序的了。下方就是希尔排序的具体执行步骤,如下所示:
六、堆排序
堆排序比希尔排序更为高效,其时间复杂度为O(nlog2n)。下方的“堆排序”是根据大顶堆来进行排序的,大顶堆第一个值是序列中最大的,我们可以利用这一点获取无序序列中最大的那个值。首先我们将序列调整为大顶堆,然后把大顶堆的第一个值与最后一个值进行交换,然后再将剩下的序列调整成大顶堆,然后进行下一轮的替换。
七、归并排序
归并排序的时间复杂度也是O(nlog2n)。归并排序就是将无序数组拆分成多个只有一个元素的数组,然后进行两两合并。在合并的过程中将两个数组中的元素进行比较,将较小的放在前方,两个有序的数组合并后依然是有序的,然后再次进行两两合并,直到合并成一个数组为止。下方就是归并排序的执行顺序,从执行过程中,我们可以清楚的看到在排序过程中被分割的小的有序序列。归并排序的执行过程如下所示:
八、快速排序
快速排序的时间复杂度为O(nlog2n)。下方是快速排序的执行步骤,快速排序是利用里分治法的思想。从无序序列中取出一个值,比该值大的放在前方,比该值小的放在后方。然后递归执行前半部分和后半部分依次递归下去,我们的序列就是有序的了。
九、基数排序
下方是基数排序的运行效果,我们先输入1000个元素,生成1000个随机数,选择基数排序。如下所示:
十、上述排序的比较
关于上述排序的比较,在此就不做过多赘述了,就引用“维基百科”中的表格来说明吧,如下所示:
今天博客中所涉及的Demo依然会在github上进行分享,分享地址如下。