Essential Swift Programming Snippets and Algorithms
Essential Swift Programming Snippets and Algorithms
Loops
Loop Forward
// Loop forward
for i in 0..Loop in Reverse
// Loop in reverse
for index in stride(from: 5, through: 1, by: -1) {
print(index) // 5, 4, 3, 2, 1
}
// OR
for i in (0..<10).reversed() {
print(i)
}Strings
String Manipulation
- Convert String to Array of Strings containing 1 Character:
var strArr = str.characters.map { String($0) }Join Array of Strings into 1 String:var str = strArr.joined(separator: "")Split String into array (requires import Foundation):import Foundation
let fullNameArr = fullName.components(separatedBy: " ")Split String into Characters (returns array of Subsequence):let subsequences = str.characters.split(separator: " ")
String(subsequences[0]) // to use as stringConvert String to Array of Characters:sChars = Array(string.characters)String/Character to Int
Convert Character to Int value (ASCII or Unicode value):
for char in string.unicodeScalars {
print(char.value)
}Get Int value (Unicode point) of a Character from a String:
extension Character {
var unicodeValue: UInt32 {
return String(self).unicodeScalars.first!.value
}
// OR
var charValue: UInt16 {
return (String(self) as NSString).character(at: 0)
}
}String Index
Need to have String.Index to access individual characters in a String:
str.startIndex// Index corresponding to 0str.endIndex// Index corresponding to N-1
Advance Index
let s = "abcdef"
let idx = s.index(s.startIndex, offsetBy: 5)
s[idx] // → "f" (the Character, not the String)Index From the Back
let s = "abcdef"
let rIdx = s.index(s.endIndex, offsetBy: -1)
// s[rIdx] → "f" (the Character, not the String) // Note: endIndex is not valid subscript
let rIdx2 = s.index(rIdx, offsetBy: -1)
s[rIdx2] // → "e" (the Character, not the String)Safe Index
let safeIdx = s.index(s.startIndex, offsetBy: 400, limitedBy: s.endIndex)
safeIdx // → nilString Slicing using Index
s[s.startIndex..Array
Slice Array
Array(numbers[0..Elements Dropping
Note: drop... methods return a new array slice.
var a = [1,2,3]
var b = Array(a.dropFirst()) // Works even if a is empty
a.dropFirst(5) // Works even if greater than length of a
a.dropLast()
a.dropLast(4)Character
Check if Character is Alphanumeric (Lowercase Example)
extension Character {
var isAlphanumeric: Bool {
return (self >= "a" && self <= "z") || (self >= "0" && self <= "9") // Add "A" and "Z" if needed
}
}Numbers
Absolute Value
abs(num) // If Int, returns Int too, if Double, returns DoubleInfinity and NaN (Float, CGFloat, Double only)
Double.infinity, Double.nan, -Double.infinity (negative infinity)
someDouble.isFinite
someDouble.isInfinite
someDouble < Double.infinity
someDouble = Double.greatestFiniteMagnitude
someDouble.isInfinite // falseMisc Functions
Swap Values
- Tuple swapping (Recommended):
var b = [1,2,3,4,5]
(b[0], b[1]) = (b[1], b[0])swap(&b[0], &b[1]) // Caution: Returns an error if indices are the same.Generate Random Number
var k: Int = random() % 10 // 0 - 9Functions
Inout Parameters
func swap(wordArr: inout Array<String>, i: Int, j: Int) {
// Modify wordArr; the original array passed will also be modified on return of this function (copy-in copy-out)
}Reserve Capacity in Collections
Reserve capacity to avoid overhead of resizing:
var longestSubstring = [Character: Int](minimumCapacity: 256)
var dict = [Int:Int]()
dict.reserveCapacity(256)Big O Notation
Complexity Hierarchy (Lowest to Highest)
- O(1)
- O(log N)
- O(N)
- O(N log N)
- O(N^2)
- O(2^N)
- O(N!)
Big O Other Notes
- Doubling Sequence (e.g., 1+2+4+8+…+N):
Approaches 2N (exactly 2N-1). This is equivalent to $\sum_{i=0}^{N} 2^i = 2^{N+1} – 1$, which is still $O(2^N)$ if $N$ is the number of terms, but if $N$ is the final value, it’s $O(N)$.
- Halving Sequence (e.g., N + N/2 + N/4 + … + 1):
Approaches 2N. If $N$ is excluded: $(N/2) + (N/4) + … + 1$ approaches N, thus $O(N)$.
- Arithmetic Sequence (e.g., 1+2+3+…+N):
Equals $(N(N+1)) / 2$, resulting in $O(N^2)$.
- Recursion (e.g., Fibonacci):
Complexity is often $\text{branches}^{\text{depth}}$. For Fibonacci (two branches), this is $O(2^N)$, where $N$ is the depth.
- Nested Loops (Second loop decreases by one):
Example: $N + (N-1) + … + 1 = (N(N+1)) / 2$, resulting in $O(N^2)$.
- Loop advancing/decreasing by powers of two:
Results in $O(\log N)$.
Bits Operations
- Determine if Power of 2:
N & (N-1) == 0 - Determine Lowest Power of 2 Near N:
Repeat
N = N & (N-1)until $N$ is 0. The number of times this operation is performed is the power of 2. - Find Unique Value from 3 Pairs (Two equal, one unique):
X1 \text{ XOR } X2 \text{ XOR } X3 = \text{answer} - Swap Two Numbers Without Additional Space (XOR Swap):
x = x \text{ XOR } y y = x \text{ XOR } y x = x \text{ XOR } y - Multiplication by Powers of Two:
To multiply by two, shift left 1 time. To multiply by $2^k$, shift left $k$ times.
Heap Formulas (Array Representation)
- A heap with $n$ nodes has height $h = \lfloor\log_2(n)\rfloor$.
- If the lowest level is completely full, it contains $2^h$ nodes. The rest of the tree above it contains $2^h – 1$ nodes.
- Leaf Nodes Location: Leaf nodes are always located at array indices $\lfloor n/2 \rfloor$ to $n-1$, where $n$ is the number of nodes.
- Heapify from Array: Start processing from index $(\lfloor n/2 \rfloor) – 1$, up to 0, since indices $\lfloor n/2 \rfloor$ to $n-1$ are already leaf nodes.
- Number of Leaf Nodes in a complete binary tree (heap) is $\lceil n/2 \rceil$.
Misc Notes
Midpoint Calculation to Avoid Integer Overflow
When computing mid for binary search or merge sort:
let mid = left + ((right - left) / 2)Reallocation Factor in Swift
- Array: 2
- String: 2
- Dictionary: 1.333
