Blog by Frank

Swift: Math Algorithm

BFS

BFS and DFS Templates Algorithms in Swift

LRU - Least Recently Used

https://www.jianshu.com/p/e09870b60046 那什么是 LruCache 呢?其实 LRU(Least Recently Used) 的意思就是近期最少使用算法,它的核心思想就是会优先淘汰那些近期最少使用的缓存对象。

class ListNode {
    var key: Int
    var value: Int
    var next: ListNode?
    var prev: ListNode?
    
    init(key: Int, value: Int) {
        self.key = key
        self.value = value
    }
}

class LRUCache {
    private var cache = [Int: ListNode]()
    // 最大size
    private var max_size = 0
    // 当前size
    private var cur_size = 0
    // 头
    private var head: ListNode?
    // 尾
    private var tail: ListNode?
    
    init(_ capacity: Int) {
        max_size = capacity
    }
    
    public func get(_ key: Int) -> Int {
        if let node = cache[key] {
            moveToHead(node: node)
            return node.value
        }
        return -1
    }
    
    public func put(_ key: Int, _ value: Int) {
        if let node = cache[key] {
            node.value = value
            moveToHead(node: node)
        } else {
            let node = ListNode(key: key, value: value)
            
            addNode(node: node)
            cache[key] = node
            
            cur_size += 1
            if cur_size > max_size {
                removeTail()
                cur_size -= 1
            }
        }
    }
    
    /// 添加节点到头部
    private func addNode(node: ListNode) {
        if self.head == nil {
            self.head = node
            self.tail = node
        } else {
            let temp = self.head!
            self.head = node
            self.head?.next = temp
            temp.prev = self.head
        }
    }
    
    /// 移动到头部
    private func moveToHead(node: ListNode) {
        if node === self.head {
            return
        }
        
        let prev = node.prev
        let next = node.next
        prev?.next = next
        if next != nil {
            next!.prev = prev
        } else {
            self.tail = prev
        }
        let origin = self.head
        self.head = node
        self.head?.next = origin
        origin?.prev = self.head
    }
    
    /// 删除尾部
    @discardableResult
    private func removeTail() -> ListNode? {
        if let tail = self.tail {
            cache.removeValue(forKey: tail.key)
            self.tail = tail.prev
            self.tail?.next = nil
            return tail
        }
        return nil
    }
}

let cache = LRUCache(3)
cache.put(1, 1)
cache.put(2, 2)
cache.put(3, 3)
cache.put(4, 4)
print(cache.get(4))
print(cache.get(3))
print(cache.get(2))
print(cache.get(1))
print("==========")
cache.put(5, 5)
print(cache.get(1))
print(cache.get(2))
print(cache.get(3))
print(cache.get(4))
print(cache.get(5))

/**
print("==========")
4
3
2
-1
==========
-1
2
3
-1
5
==========
*/

Dynamic Programming

一个例子带你走进动态规划 – 青蛙跳阶问题

暴力递归

★leetcode原题:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。

有些小伙伴第一次见这个题的时候,可能会有点蒙圈,不知道怎么解决。其实可以试想:

Tree

Preorder Traverse

二叉树的前序遍历

class Solution {
   func preorderTraversal(_ root: TreeNode?) -> [Int] {
        var res: [Int] = []
       if nil == root {
           return res
       }
       
       var stack: [TreeNode?] = []
       var node: TreeNode? = root
       
       while !stack.isEmpty || nil != node {
           while nil != node {
               res.append(node!.val)
               stack.append(node)
               node = node?.left
           }
           node = stack.removeLast()?.right
       }
       return res
    }
}

Prime Number

A prime number is a whole number greater than 1 whose only factors are 1 and itself.

2, 3, 5, 7, 11, 13, 17, 19, 23, 29 are prime numbers.

Primes vs composites

Fastest Prime Checker by Noah Wilder on the stack overflow

Swift 4.2, Xcode 10.1

This prime checking function and extension is the most efficient as it checks the divisibility of only $\frac{1}{2}\sqrt{n}$ integers.

Complexity: $O(\frac{1}{2} \sqrt{n})$

///  https://stackoverflow.com/questions/31105664/check-if-a-number-is-prime
///  Check if a number is prime?
import Foundation
func isPrime(for number: Int) -> Bool {
    guard number >= 2 else { return false }
    guard number != 2 else { return true }
    guard number % 2 != 0 else { return false }
    
    /// `stride(from: 3, to: Int(sqrt(Double(number))), by: 2)`
    /// traverse 3 5 7 9 11.... odd number
    ///
    /// `stride(from:to:by:).contains(where:)`
    /// If number % index = 1, then it's not prime.
    /// If the odd number contains number that the specific number can be divided by. Then it's not prime.
    /// So there is a negation operator before stride.
    /// True -> Prime False -> Not Prime
    return !stride(from: 3, to: Int(sqrt(Double(number))), by: 2).contains(where: { index in
        return number % index == 0
    })
}

print(isPrime(for: 4))

Extension

extension Int {
    ///  A prime number is a whole number greater than 1 whose only factors are 1 and itself.
    var isPrime: Bool {
        guard self >= 2 else { return false }
        guard self != 2 else { return true }
        guard self % 2 != 0 else { return false }
        
        return !stride(from: 3, to: Int(sqrt(Double(self))), by: 2).contains(where: { index in
            return self % index == 0
        })
    }
}

var number = 3
number.isPrime

Get odd number in C

C get odd numbers between a range and store it in int array - by user10543939 on the stack overflow

int* oddNumbers(int start, int end, int* result_count) {
    int *result;
    int i;
    
    /// @brief #define	assert(e) \
    /// (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __ASSERT_FILE_NAME, __LINE__, #e) : (void)0)
    /// @param start 
    /// @param end 
    /// @param result_count 
    /// @return 
    assert(result_count && start <= end && INT8_MIN < end);

    // if start is even, then add 1 to be odd
    start += !(start % 2);
    // if end is even, then minus 1 to be odd
    end -= !(end % 2);

    // calculate array size
    *result_count = (end - start) / 2 + 1;
    result = malloc(*result_count * sizeof(result));
    
    if(!result) return NULL;

    // fill in numbers in the result
    for (i = 0; start <= end; i++, start += 2) result[i] = start;

    return result;
}

int main() {
    int min = 30;
    int max = 85;
    // address of count
    int count;
    int *numbers = oddNumbers(min, max, &count);
    
    for (int i = 0; i < count; i++) {
        printf("%d ", numbers[i]);
    }
    // Don't forget to `free()` the returned pointer when you are done using it.
    free(numbers);
}

Stride and generics template in C++

template<typename T>
T * stride(T start, T end, T step) {
    T * arrayOfOutPut;

    int sizeOfArray = (end - start) / step + 1;
    arrayOfOutPut = (T *)malloc(sizeOfArray * sizeof(T));

    for(int i = 0; i < sizeOfArray; i++) {
        arrayOfOutPut[i] = start + i * step;
        std::cout << arrayOfOutPut[i] << " ";
    }

    return arrayOfOutPut;
}

int main() {
    double start = 2;
    double end = 5;
    double step = 0.5;

    int sizeOfArray = (end - start) / step + 1;
    double* a = stride(start, end, step);
    std::cout << std::endl;
    for(int i = 0; i < sizeOfArray; i++) {
        std::cout << a[i] << " ";
    }
}

valarray

#include <iostream>
#include <valarray>

bool isPrime(int number) {
    if (!(number > 2)) return false;
    if (!(number != 2)) return true;
    if (!(number % 2 != 0)) return false;

    int end = number;
    int start = 3;
    int step = 2;
    int sizeOfArray = sizeOfArray = (end - start) / step + 1;
    
    std::valarray<int> array(sizeOfArray);
    for(int i = 0; i < sizeOfArray; i++) {
        array[i] = i;
    }

    std::slice slcOfArray(start, end, step);

    std::valarray<int> valArrayOutput = std::valarray<int>(array[slcOfArray]);
    
    for(int i = 0; i < sizeOfArray; i++) {
        if (number % valArrayOutput[i] == 0) return false;
    }
    return true;
}

int main() {
    int numberCount = 0;

    int startNumber = 200;
    int endNumber = 299;

    for(int i = startNumber; i <= endNumber; i++) {
        if(isPrime(i)) {
            numberCount += 1;
            std::cout << i;
            if(numberCount == 8) {
                std::cout << std::endl;
                numberCount = 0;
            } else {
                std::cout << " ";
            }
        }
    }
}

Sieve of Eratosthenes

Sieve of Eratosthenes - GeeksForGeeks

Khan Academy - Sieve of Eratosthenes

For all numbers a: from 2 to sqrt(n)
    IF a is unmarked THEN
        a is prime
        for all multiples of a (a < n)
            mark multiples as composite

All unmarked numbers are prime!
#include <stdio.h>

void SieveOfEratosthenes(int n) {
    
    bool prime[n + 1];
}