您的位置:首页 > 移动开发 > Swift

[Swift]面试题系列之常见算法

2017-03-20 00:00 633 查看
摘要: 本文参考自
[iOS面试题系列之常见算法](http://blog.csdn.net/yangshebing21/article/details/51292477)
并用Swift实现的版本。对自己学习算法和Swift做个记录。

[Swift]面试题系列之常见算法

本文参考自
iOS面试题系列之常见算法
并用Swift实现的版本。对自己学习算法和Swift做个记录。

1.冒泡排序

冒泡排序笔记:
冒泡排序的重点在于相邻两两比较,发现顺序不对,就换位置。

for i in 0..<count-1
for j in 0..<count-1-i
if a[j] < a[j+1] 降序
or
if a[j] > a[j+1] 升序
换位置

func sortByBubble(array : [Int], rise : Bool) -> [Int]
{
var sortArray = array
let num = array.count
for i in 0..<(num-1) {
for j in 0..<(num-1-i) {

var exchange = false
if rise {
if sortArray[j] > sortArray[j+1] {
exchange = true
}
}else {
if sortArray[j] < sortArray[j+1] {
exchange = true
}
}

if exchange {
let tmp = sortArray[j]
sortArray[j] = sortArray[j+1]
sortArray[j+1] = tmp
}
}
}
return sortArray
}
var array = [24, 17, 85, 13, 9, 54, 76, 45, 5, 63]
let array_sortByBubble = sortByBubble(array: array, rise: false)
let array_sortByBubble2 = sortByBubble(array: array, rise: true)

2.升序排序(选择排序)

//选择排序笔记:
//选择排序的重点在于控制交换的字数
//外层循环每次都会确定一个数据的位置,n次循环结束 n个数据的位置也就确定了
//注意: 根据循环方向不同,升序or降序 在循环过程中确定数据的大小趋势也不同

// === 讨论下 正向循环的情况 升序或者降序,数据的趋势
//=============================
//  正向循环 > 数据从低位开始确定
//          - 升序 由小到大
//          - 降序 由大到小
//=============================
//  逆向循环 > 数据从高位开始确定
//          - 升序 由大到小
//          - 降序 由小到大
//=============================

// ===伪代码===
// index
// for i in 0..<count-1
//   index = i
//   for j in i+1..<count
//
//      if a[index] < a[j] 降序
//      or
//      if a[index] > a[j] 升序
//      index = j
//
//   if(index != i)
//      换位置

func sortByChoose(array : [Int], rise : Bool) -> [Int]
{
var sortArray = array
let n = array.count
var index : Int

for i in 0..<n-1 {

index = i
for j in i+1..<n {
if rise {
if(sortArray[index] > sortArray[j]) {
index = j
}
}else {
if(sortArray[index] < sortArray[j]) {
index = j
}
}
}

if(index != i) {
let tmp = sortArray[i]
sortArray[i] = sortArray[index]
sortArray[index] = tmp
}
}

return sortArray
}

var numAr : [Int] = [86, 37, 56, 29, 92, 73, 15, 63, 30, 8];

let newA = sortByChoose(array: numAr, rise: true)
let newB = sortByChoose(array: numAr, rise: false)

3.快速排序算法

参考 白话经典算法系列之六 快速排序 快速搞定

该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。

func quickSortPartition(array : [Int], left : Int, right: Int, rise : Bool) ->([Int], Int)
{
var i = left
var j = right
let key = array[i]

var sortArray = array

while (i < j) {

while (i < j && (rise ? (key <= sortArray[j]) : (key >= sortArray[j])) ) {

j -= 1;
}
guard i < j else {
continue
}

sortArray[i] = sortArray[j];

while (i < j && (rise ? (key >= sortArray[i]) : (key <= sortArray[i])) ) {

i += 1;
}
guard i < j else {
continue
}

sortArray[j] = sortArray[i];
}

sortArray[i] = key;
return (sortArray, i)
}

func sortByFast(array : [Int], left : Int, right: Int, rise : Bool) -> [Int]
{
guard left < right else {
return array
}

var (sortArray, p) = quickSortPartition(array: array, left: left, right: right, rise: rise)

sortArray = sortByFast(array: sortArray, left: left, right: p-1, rise: rise)
sortArray = sortByFast(array: sortArray, left: p+1, right: right, rise: rise)

return sortArray
}

var sortByFast_list : [Int] = [86, 37, 56, 29, 92, 73, 15, 63, 30, 8];
let sortByFast_list_count = sortByFast_list.count
let sortByFast_list2 = sortByFast(array: sortByFast_list, left: 0, right: sortByFast_list_count-1 , rise: true)
let sortByFast_list3 = sortByFast(array: sortByFast_list, left: 0, right: sortByFast_list_count-1 , rise: false)

4.归并排序

白话经典算法系列之五 归并排序的实现

func merge(sourceArr :[Int], tempArr :[Int], startIndex :Int , midIndex :Int , endIndex :Int )->([Int] , [Int])
{
var mtempArr = tempArr
var msourceArr = sourceArr

var i = startIndex;
var j = midIndex + 1;
var k = startIndex;

while (i != midIndex + 1 && j != endIndex + 1) {
if (sourceArr[i] >= sourceArr[j]) {
mtempArr[k] = sourceArr[j];
j += 1
} else {
mtempArr[k] = sourceArr[i];
i += 1
}
k += 1
}
while (i != midIndex + 1) {

mtempArr[k] = sourceArr[i];
k += 1
i += 1
}
while (j != endIndex + 1) {

mtempArr[k] = sourceArr[j];
k += 1
j += 1
}

for index in startIndex...endIndex {
msourceArr[index] = mtempArr[index];
}

return (msourceArr, mtempArr)
}

func sort(souceArr: [Int], tempArr: [Int], startIndex: Int, endIndex: Int)->([Int] , [Int])
{
var midIndex: Int

if (startIndex < endIndex) {

midIndex = (startIndex + endIndex) / 2;

var (msouceArr, mtempArr) = sort(souceArr: souceArr, tempArr: tempArr, startIndex: startIndex, endIndex: midIndex);
(msouceArr, mtempArr) = sort(souceArr: msouceArr, tempArr: mtempArr, startIndex: midIndex + 1, endIndex: endIndex);
(msouceArr, mtempArr) = merge(sourceArr: msouceArr, tempArr: mtempArr, startIndex: startIndex, midIndex: midIndex, endIndex: endIndex);
return (msouceArr, mtempArr)
}
return (souceArr, tempArr)
}

//test

let numArr = [86, 37, 56, 29, 92, 73, 15, 63, 30, 8];

let tempArr : [Int] = Array.init(repeating: 0, count: numArr.count);

let (msouceArr, mtempArr) = sort(souceArr: numArr, tempArr: tempArr, startIndex: 0, endIndex: 9);

5.实现二分查找算法

二分查找法的基本实现

普通实现
func bsearchWithoutRecursion(array: [Int], low: Int, high: Int, target: Int) -> Int
{
var low = low
var high = high

while(low <= high) {

let mid = (low + high) / 2;

if(array[mid] > target) {
high = mid - 1;
}else if(array[mid] < target) {
low = mid + 1;
}else {
//findthetarget

return mid
}
}

//the array does not contain the target
return -1;

}

递归实现
func binary_search(array: [Int], low: Int, high: Int, target: Int) -> Int
{
let mid = low + (high - low) / 2;
if(low > high) {
return -1
} else {

if(array[mid] == target){
return mid;
}else if(array[mid] > target){
return binary_search(array: array, low: low, high: mid-1, target: target)
} else {
return binary_search(array: array, low: mid+1, high: high, target: target)
}
}
}

let numArr = [1, 4, 7, 8, 9, 13, 15, 24, 30, 81];
binary_search(array: numArr, low: 0, high: numArr.count-1, target: 24)
bsearchWithoutRecursion(array: numArr, low: 0, high: numArr.count-1, target: 24)

6、 如何实现链表翻转(链表逆序)?

//思路:每次把第二个元素提到最前面来。

class Node :CustomStringConvertible
{
var num: Int
var next: Node?
init(_ num: Int) {
self.num = num
next = nil
}

var description: String {
return "num=\(num) next=\(next)"
}
}

func createLinkList(length: Int) -> Node?
{
print("createLinkList")
if (length <= 0) {
return nil
}
var head : Node
var p : Node
var q : Node

var number = 1;
head = Node.init(number);
q = head

while number < length {

number += 1
p = Node.init(number);
q.next = p
q = p;
}
return head;
}

func reverseFunc1(head: Node?) ->Node?
{
var p = head
var q :Node?

while (p) != nil {
print("\(q)")
let pnext = p?.next
p?.next = q
q = p;
p = pnext;
}
return q!;
}

let head = createLinkList(length: 7)
print("head=   \(head)")

let reHead = reverseFunc1(head: head)
//printLinkList(head: reHead)
print("reHead= \(reHead)")

7、 实现一个字符串“how are you”的逆序输出(编程语言不限)。如给定字符串为“hello world”,输出结果应当为“world hello”。

func spliterFunc(p: String) ->String
{
var c: [[Character]] = Array.init(repeating: Array.init(repeating: "\0", count: 10), count: 10)

var i = 0
var j = 0

for char in p.characters {

if (char == " ") {

i += 1
j = 0;
} else {

c[i][j] = char
j += 1

}
}

print(c)
var  rep = ""

for k in 0...i {
let index = i-k
rep += String.init(c[index])
if index>0 {
rep += " "
}else {
rep += "\n"
}
}

return rep;
}

spliterFunc(p: "hello world")

8、 二叉树的先序遍历为FBACDEGH,中序遍历为:ABDCEFGH,请写出这个二叉树的后序遍历结果

口诀 :前序遍历-中左右 中序遍历-左中右 后序遍历-左右中

答案 ADECBHGF

9、 打印2-100之间的素数。

func isPrime(n :Int) ->Bool
{
let max = Int(sqrt(Double(n)))
if max<2 {
if(n % 2 == 0) {
return false
}
return true
}

for i in 2...max {
if(n % i == 0) {
return false
}
}

return true;
}

for i in 2...100 {

var r = isPrime(n: i)

if (r) {
print("\(i)");
}
}

10、 求两个整数的最大公约数。

func gcd(a :Int, b :Int) -> Int
{
var temp = 0
var a = a
var b = b

if (a < b) {
temp = a
a = b
b = temp
}

while (b != 0) {
temp = a % b
a = b
b = temp
}

return a
}

gcd(a: 100, b: 3)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Swift 算法