《剑指Offer》阅读笔记(swift):栈(3题)、递归(4题)、回溯法(2题)

398 阅读2分钟

我的Github地址

小码哥《恋上数据结构与算法》笔记

极客时间《iOS开发高手课》笔记

iOS大厂面试高频算法题总结

iOS面试资料汇总

  • 栈(3道):
    • 剑指Offer(9):用两个栈实现队列
    • 剑指Offer(30):包含min函数的栈
    • 剑指Offer(31):栈的压入、弹出序列
  • 递归(4道):
    • 剑指Offer(10):裴波那契数列
    • 剑指Offer(10):跳台阶
    • 剑指Offer(10):变态跳台阶
    • 剑指Offer(10):矩形覆盖
  • 回溯法(2道):
    • 剑指Offer(12):矩阵中的路径
    • 剑指Offer(13):机器人的运动范围

面试题9:用两个栈实现队列

题目一

思路一

代码

var stack1 = [Int]()
var stack2 = [Int]()

func appendTail(_ value: Int) {
    stack1.append(value)
}

func deleteHead() -> Int {
    if stack2.isEmpty {
        while !stack1.isEmpty {
            stack2.append(stack1.popLast()!) //不能removelast,此函数不会改变stack1的count
        }
    }
    return stack2.isEmpty ? -1 : stack2.popLast()! //记住-1
}

面试题30:包含min函数的栈

题目一

思路一

代码


	class MinStack {
		
		var array = [Int]()
		var minArray = [Int]()
		/** initialize your data structure here. */
		init() {
			
		}
		
		func push(_ x: Int) {
			array.append(x)
			
			if minArray.count == 0 {
				minArray.append(x)
			} else {
				minArray.append(min(x, minArray.last!))
			}
		}
		
		func pop() {
			array.removeLast()
			minArray.removeLast()
		}
		
		func top() -> Int {
			return array.last!
		}
		
		func getMin() -> Int {
			return minArray.last!
		}
	}

面试题31:栈的压入、弹出序列

题目一

思路一

代码

    func validateStackSequences(_ pushed: [Int], _ popped: [Int]) -> Bool {
        guard pushed.count == popped.count else {
            return false
        }
        var stack = [Int]()
        var popped = popped
        for num in pushed {
            stack.append(num)
            while stack.count > 0, popped.count > 0, stack.last! == popped.first! {
                stack.removeLast()
                popped.removeFirst()
            }
        }
        return stack.isEmpty
    }

面试题10:裴波那契数列

题目一

思路一

代码

    func fib(_ n: Int) -> Int {
        if n == 0 { return 0 }
        var dp = [Int](repeating: 0, count: n + 1)
        dp[1] = 1;
        if n >= 2 {
            for i in 2...n {
                dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007
            }
        }
        return dp[n]
    }

题目二:青蛙跳台阶问题

思路一

代码

func numWays(_ n: Int) -> Int {
    if n == 0 { return 1}
    var nums = [Int](repeating: 0, count: n + 1)
    nums[0] = 1
    nums[1] = 1
    if n >= 2 {
        for i in 2...n {
            // 计算一次就存储到数组里面,用空间来换时间
            nums[i] = (nums[i - 1] + nums[i - 2]) % 1000000007
        }
    }
    return nums[n]
}

题目三:变态跳台阶

  • 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路一

代码

public class Solution {
    public int JumpFloorII(int target) {
        if(target<=0)
            return 0;
        if(target == 1||target ==2)
            return target;
        else
            return 2*JumpFloorII(target-1);
    }
}

题目四:矩形覆盖

思路一

代码

class Solution {
public:
    int rectCover(int number) {
        if(number <= 2){
            return number;
        }
        int first = 1, second = 2, third = 0;
        for(int i = 3; i <= number; i++){
            third = first + second;
            first = second;
            second = third;
        }
        return third;
    }
};

面试题12:矩阵中的路径

题目一

思路一

代码


//注意:
/*
 1.注意使用visited处理访问过的位置(这里使用一个小技巧,记录元素的序号)
 2.注意边界判断
 3.注意hasPath的循环终止条件,即if pathLength == word.count { return true } 位置。
 4.查找上左下右,使用两个数组,代码写起来更容易理解和不冗余。
 */
class Solution {
    let dx = [0,1,0,-1]
    let dy = [1,0,-1,0]
    func exist(_ board: [[Character]], _ word: String) -> Bool {
        guard board.count > 0 && word.count > 0 else {
            return false
        }
        var visited = [Int]()
        for i in 0..<board.count {
            for j in 0..<board.first!.count {
                if hasPath(board, i, j, word, 0, visited) {
                    return true
                }
                visited.removeAll()
            }
        }
        return false
    }
    
    func hasPath(_ board: [[Character]], _ row: Int, _ col: Int, _ word: String, _ pathLength: Int, _ visited: [Int]) -> Bool {
        let cur = board[row][col]
        let char = word[word.index(word.startIndex, offsetBy: pathLength)]
        var visited = visited
        var pathLength = pathLength
        if cur == char {
            visited.append(row * board.first!.count + col)
            pathLength += 1
            if pathLength == word.count {
                return true
            }
            for index in 0...3 {
                let newRow = row + dx[index]
                let newCol = col + dy[index]
                if newRow >= 0 && newRow < board.count && newCol >= 0 && newCol < board.first!.count {
                    if visited.contains(newRow * board.first!.count + newCol) {
                        continue
                    }
                    if hasPath(board, newRow, newCol, word, pathLength, visited) {
                        return true
                    }
                }
            }
        } else {
            return false
        }
        return false
    }
}

面试题13:机器人的运动范围

题目一

思路一