LeetCode Problems

1. Optional Handling Çok Önemli!

// MARK: - Optional Basics
var value: Int? = 5
var empty: Int? = nil

// ❌ Crash risk
let result = value! + 10  // Force unwrap - kullanma!

// ✅ Safe unwrapping methods

// 1. if let (en yaygın)
if let unwrapped = value {
    print(unwrapped + 10)  // 15
}

// 2. guard let (fonksiyon başında)
func process(_ num: Int?) -> Int {
    guard let num = num else {
        return 0  // Early return
    }
    return num * 2
}

// 3. Nil coalescing (?? - varsayılan değer)
let result = value ?? 0  // value nil ise 0 kullan
print(result)  // 5

// 4. Optional chaining
var dict = [String: Int]()
dict["key"] = 5
let doubled = dict["key"].map { $0 * 2 }  // Optional(10)

// LeetCode'da en çok kullanacağın
var freq = [Character: Int]()
freq["a", default: 0] += 1  // Nil ise 0, değilse mevcut değer

// Dictionary optional handling
if let count = freq["a"] {
    print("Found: \(count)")
} else {
    print("Not found")
}

2. Array Operations

// MARK: - Array Declaration (İki Farklı Yol)

// Versiyon 1: Array Literal
var arr1: [Int] = []
// Swift'e diyorsun: "Bu Int array'i, değeri boş literal"
// Tip sol tarafta belirtilmiş, sağ tarafta sadece []

// Versiyon 2: Initializer Call
var numbers = [Int]()
// Swift'e diyorsun: "Int array'inin init() metodunu çağır"
// Tip sağ tarafta, () = initializer çağrısı

// MARK: - Array Creation
var empty = [Int]()
var filled = Array(repeating: 0, count: 5)  // [0, 0, 0, 0, 0]
var range = Array(0..<10)  // [0,1,2,...,9]
var literal = [1, 2, 3, 4, 5]

// MARK: - Array Access
var arr = [10, 20, 30, 40, 50]

// Index access
let first = arr[0]           // 10
let last = arr[arr.count - 1]  // 50

// Safe access
let safe = arr.indices                // 0..<5
let safe = arr.indices.contains(1)    // true
let safe = arr.indices.contains(8)    // false
let safe = arr.indices.contains(1) ? arr[1] : nil   // Optional(20)
let safe = arr.indices.contains(8) ? arr[8] : nil   // nil

// First/Last (optional)
let optFirst = arr.first     // Optional(10)
let optLast = arr.last       // Optional(50)

// MARK: - Array Modification
arr.append(60)               // [10, 20, 30, 40, 50, 60]
arr.insert(5, at: 0)         // [5, 10, 20, 30, 40, 50, 60]
arr.remove(at: 0)            // [10, 20, 30, 40, 50, 60]
arr.removeLast()             // [10, 20, 30, 40, 50]
arr.removeFirst()            // [20, 30, 40, 50]
arr.removeAll()              // []

// MARK: - Array Slicing
arr = [1, 2, 3, 4, 5]
let slice = arr[1..<4]       // [2, 3, 4] - ArraySlice type
let array = Array(arr[1..<4])  // Convert to Array

let first3 = arr.prefix(3)   // [1, 2, 3]
let last2 = arr.suffix(2)    // [4, 5]

// MARK: - Array Algorithms
arr.reverse()                // In-place reverse
arr.sort()                   // In-place sort
let sorted = arr.sorted()    // New sorted array
arr.swapAt(0, 1)             // Swap elements at indices

// MARK: - Array Iteration
for num in arr {
    print(num)
}

// With index
for (index, num) in arr.enumerated() {
    print("\(index): \(num)")
}

// Manual index iteration
for i in 0..<arr.count {
    print(arr[i])
}

// Reverse iteration
for i in stride(from: arr.count - 1, through: 0, by: -1) {
    print(arr[i])
}

3. String Operations

// MARK: - String to Array (ÇOK ÖNEMLİ!)
let s = "hello"

// Swift'te String indexing zor, Array'e çevir!
let chars = Array(s)         // [Character]
print(chars[0])              // "h"
print(chars[4])              // "o"

// String'den geri
let str = String(chars)      // "hello"

// MARK: - String Properties
s.count                      // 5
s.isEmpty                    // false

// MARK: - String Manipulation
var mutable = "hello"
mutable.append("!")          // "hello!"
mutable += " world"          // "hello! world"

// Character append
mutable.append(Character("?"))  // "hello! world?"

// MARK: - String Iteration
for char in s {
    print(char)  // Character type
}

// MARK: - Character Checks
let char: Character = "a"
char.isLetter                // true
char.isNumber                // false
char.isWhitespace            // false
char.isUppercase             // false
char.isLowercase             // true

// MARK: - Case Conversion
s.lowercased()               // "hello"
s.uppercased()               // "HELLO"

// MARK: - ASCII Value (HashMap için önemli!)
let a: Character = "a"
let aValue = a.asciiValue!   // 97
let index = Int(a.asciiValue! - Character("a").asciiValue!)  // 0

// Reverse: ASCII'den Character'e
let char2 = Character(UnicodeScalar(97)!)  // "a"

// MARK: - String Split
let sentence = "one two three"
let words = sentence.split(separator: " ")  // [Substring]
// Substring yerine String yapıyoruz çünkü Substring original string'e referans tutar
// Eğer original string büyükse ve sadece küçük bir parçasını tutuyorsan, tüm string hafızada kalır!
let wordsArray = sentence.split(separator: " ").map { String($0) }  // [String]

4. Dictionary (HashMap)

// MARK: - Dictionary Declaration (İki Farklı Yol)

// Versiyon 1: Dictionary Literal
var dict1: [String: Int] = [:]
// Swift'e diyorsun: "Bu String-Int dictionary'si, değeri boş literal"
// Tip sol tarafta belirtilmiş, sağ tarafta sadece [:]

// Versiyon 2: Initializer Call
var dict2 = [String: Int]()
// Swift'e diyorsun: "String-Int dictionary'nin init() metodunu çağır"
// Tip sağ tarafta, () = initializer çağrısı

// Character key için (LeetCode'da sık kullanılır)
var freq: [Character: Int] = [:]
var freq2 = [Character: Int]()

// MARK: - Dictionary Creation
var dict3 = ["a": 1, "b": 2]

// MARK: - Dictionary Access
dict3["a"]                   // Optional(1)
dict3["c"]                   // nil

// ❌ Force unwrap - Tehlikeli! Key yoksa crash
dict3["a"]!                  // 1
dict3["c"]!                  // 💥 Fatal error: unexpectedly found nil

// ✅ Safe access
if let value = dict3["a"] {
    print(value)
}

let value = dict3["a"] ?? 0  // Default value

// MARK: - Dictionary Modification
dict3["c"] = 3               // Insert/Update
dict3["a"] = nil             // Remove
dict3.removeValue(forKey: "b")  // Optional(2) - Remove and return value

// Default value pattern (ÇOK KULLANILIR!)
dict3["d", default: 0] += 1  // If nil, use 0, then increment

// MARK: - Dictionary Iteration
for (key, value) in dict3 {
    print("\(key): \(value)")
}

// Keys only
for key in dict3.keys {
    print(key)
}

// Values only
for value in dict3.values {
    print(value)
}

// Convert to arrays
let keysArray = Array(dict3.keys)
let valuesArray = Array(dict3.values)

5. Set

// MARK: - Set Declaration (İki Farklı Yol)

// Versiyon 1: Set Literal
var set1: Set<Int> = []
// Swift'e diyorsun: "Bu Int Set'i, değeri boş literal"
// Tip sol tarafta belirtilmiş, sağ tarafta sadece []

// Versiyon 2: Initializer Call
var set2 = Set<Int>()
// Swift'e diyorsun: "Int Set'inin init() metodunu çağır"
// Tip sağ tarafta, () = initializer çağrısı

// MARK: - Set Creation
var set3: Set = [1, 2, 3, 4, 5]  // Tip inference ile

// MARK: - Set Operations
set3.insert(6)               // Add
set3.remove(1)               // Remove
set3.contains(2)             // true - O(1)!

// MARK: - Set Iteration
for num in set3 {
    print(num)  // Unordered!
}

// MARK: - Set Math
let a: Set = [1, 2, 3, 4]
let b: Set = [3, 4, 5, 6]

a.union(b)                   // [1, 2, 3, 4, 5, 6]
a.intersection(b)            // [3, 4]
a.subtracting(b)             // [1, 2]
a.symmetricDifference(b)     // [1, 2, 5, 6]

6. Control Flow

// MARK: - If-Else
let x = 10

if x > 5 {
    print("Greater")
} else if x == 5 {
    print("Equal")
} else {
    print("Less")
}

// MARK: - Guard (Early return pattern)
func divide(_ a: Int, _ b: Int) -> Int? {
    guard b != 0 else {
        return nil  // Early return
    }
    return a / b
}

// Guard with optionals
func process(_ arr: [Int]?) -> Int {
    guard let arr = arr, !arr.isEmpty else {
        return 0
    }
    return arr[0]
}

// MARK: - Switch (Pattern matching)
let value = 5

switch value {
case 0:
    print("Zero")
case 1...10:  // Range
    print("Between 1 and 10")
case let x where x > 10:  // Condition
    print("Greater than 10: \(x)")
default:
    print("Other")
}

// MARK: - Ternary Operator
let max = a > b ? a : b
let result = arr.isEmpty ? 0 : arr[0]

7. Loops

// MARK: - For Loop
for i in 0..<10 {            // 0 to 9
    print(i)
}

for i in 0...10 {            // 0 to 10 (inclusive)
    print(i)
}

// Reverse
for i in (0..<10).reversed() {
    print(i)
}

// Stride (step)
for i in stride(from: 0, to: 10, by: 2) {
    print(i)  // 0, 2, 4, 6, 8
}

for i in stride(from: 10, through: 0, by: -2) {
    print(i)  // 10, 8, 6, 4, 2, 0
}

// MARK: - While Loop
var count = 0
while count < 10 {
    print(count)
    count += 1
}

// MARK: - Loop Control
for i in 0..<10 {
    if i == 5 {
        break  // Exit loop
    }
    if i % 2 == 0 {
        continue  // Skip iteration
    }
    print(i)
}

11. Common Patterns LeetCode'da Sürekli Kullanılır!

// MARK: - Two Pointers
func twoPointers(_ arr: [Int]) {
    var left = 0
    var right = arr.count - 1
    
    while left < right {
        // Process
        left += 1
        right -= 1
    }
}

// MARK: - Sliding Window
func slidingWindow(_ arr: [Int], _ k: Int) {
    var left = 0
    
    for right in 0..<arr.count {
        // Expand window
        
        // Shrink window if needed
        while someCondition {
            left += 1
        }
    }
}

// MARK: - Frequency Counter
func frequencyCount(_ s: String) -> [Character: Int] {
    var freq = [Character: Int]()
    
    for char in s {
        freq[char, default: 0] += 1
    }
    
    return freq
}

// MARK: - Array as HashMap (a-z)
func arrayHash(_ s: String) -> [Int] {
    var freq = Array(repeating: 0, count: 26)
    let aValue = Character("a").asciiValue!
    
    for char in s {
        let index = Int(char.asciiValue! - aValue)
        freq[index] += 1
    }
    
    return freq
}

// MARK: - Seen/Visited Tracker
func hasDuplicate(_ nums: [Int]) -> Bool {
    var seen = Set<Int>()
    
    for num in nums {
        if seen.contains(num) {
            return true
        }
        seen.insert(num)
    }
    
    return false
}

// MARK: - Binary Search Template
func binarySearch(_ arr: [Int], _ target: Int) -> Int {
    var left = 0
    var right = arr.count - 1
    
    while left <= right {
        let mid = left + (right - left) / 2
        
        if arr[mid] == target {
            return mid
        } else if arr[mid] < target {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    
    return -1
}

Özet: En Çok Kullanacakların

// 1. Optional handling
if let value = dict["key"] { }
guard let value = dict["key"] else { return }
let value = dict["key"] ?? 0
dict["key", default: 0] += 1

// 2. Array basics
var arr = [Int]()
arr.append(5)
arr[0]
arr.count
arr.isEmpty

// 3. String to Array
let chars = Array(string)

// 4. Loops
for i in 0..<n { }
for (i, val) in arr.enumerated() { }

// 5. Dictionary
var freq = [Character: Int]()
freq[char, default: 0] += 1

// 6. Set
var seen = Set<Int>()
seen.insert(5)
seen.contains(5)

// 7. Character/ASCII
let index = Int(char.asciiValue! - Character("a").asciiValue!)

Edge Cases Checklist

Her problemde kontrol et!

  • guard !arr.isEmpty else { return defaultValue } - Empty input
  • if arr.count == 1 { return arr[0] } - Single element
  • if arr.count == 2 { /* handle */ } - Two elements
  • guard let value = optional else { return } - Nil/Optional
  • if i >= 0 && i < arr.count - Index bounds