常見(jiàn)算法

class ListNode {
    var val: Int
    var next: ListNode?
    init() { self.val = 0; self.next = nil; }
    init(_ val: Int) { self.val = val; self.next = nil; }
    init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
}

class TreeNode {
    var val: Int
    var left: TreeNode?
    var right: TreeNode?
    init() { self.val = 0; self.left = nil; self.right = nil; }
    init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
    init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
        self.val = val
        self.left = left
        self.right = right
    }
}

//兩數(shù)之和
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
    if nums.isEmpty { return [] }
    var dict = [Int: Int]()
    for (index, num) in nums.enumerated() {
        if let _index = dict[target-num] {
            return [_index, index]
        }
        dict[num] = index
    }
    return []
}

//三數(shù)之和 (雙指針?lè)ǎ?func threeSum(_ nums: [Int], _ target: Int) -> [[Int]] {
    var res = [[Int]]()
    var sorted = nums
    sorted.sort()
    for i in 0 ..< sorted.count {
        if sorted[i] > target {
            return res
        }
        if i > 0 && sorted[i] == sorted[i - 1] {
            continue
        }
        var left = i + 1
        var right = sorted.count - 1
        while left < right {
            let sum = sorted[i] + sorted[left] + sorted[right]
            if sum < target {
                left += 1
            } else if sum > target {
                right -= 1
            } else {
                res.append([sorted[i], sorted[left], sorted[right]])
                
                while left < right && sorted[left] == sorted[left + 1] {
                    left += 1
                }
                while left < right && sorted[right] == sorted[right - 1] {
                    right -= 1
                }
                
                left += 1
                right -= 1
            }
        }
    }
    return res
}

//兩數(shù)相加
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
    var l1 = l1, l2 = l2
    if l1 == nil && l2 == nil { return nil }
    var head: ListNode?
    var cur = head
    var c = 0
    while l1 != nil || l2 != nil {
        let a = l1?.val ?? 0
        let b = l2?.val ?? 0
        let val = (a + b + c) % 10
        c = (a + b + c) / 10
        if head == nil {
            head = ListNode(val)
            cur = head
        } else {
            cur?.next = ListNode(val)
            cur = cur?.next
        }
        l1 = l1?.next
        l2 = l2?.next
    }
    if c == 1 {
        cur?.next = ListNode(1)
    }
    return head
}

//字符串反轉(zhuǎn)
func reverse(_ str: String?) -> String? {
    guard let str = str, !str.isEmpty else { return nil }
    var strs = Array(str)
    var i = 0, j = strs.count - 1
    while i < j {
        strs.swapAt(i, j)
        i += 1
        j -= 1
    }
    return String(strs)
}

//輸入: s = "abcabcbb"
//輸出: 3
func lengthOfLongestSubstring(_ s: String) -> Int {
    var maxLength = 0
    var i = 0
    var dict = [String: Int]()
    
    for (j, c) in s.enumerated() {
        if let index = dict[String(c)] {
            i = max(i, index + 1)
        }
        maxLength = max(maxLength, j - i + 1)
        dict[String(c)] = j
    }
    return maxLength
}

//有效的括號(hào)
func isValid(_ s: String) -> Bool {
    if s.count % 2 != 0 { return false }
    let maps = [")": "(", "]": "[", "}": "{"]
    var stacks: [String] = []
    
    for c in s {
        let ss = String(c)
        if let ss_ = maps[ss] {
            if stacks.isEmpty || stacks.last != ss_ {
                return false
            }
            stacks.removeLast()
        } else {
            stacks.append(ss)
        }
    }
    return stacks.isEmpty
}

//合并兩個(gè)有序鏈表
func mergeTwoLists(_ list1: ListNode?, _ list2: ListNode?) -> ListNode? {
    guard let list1 = list1 else { return list2 }
    guard let list2 = list2 else { return list1 }
    
    if list1.val < list2.val {
        list1.next = mergeTwoLists(list1.next, list2)
        return list1
    } else {
        list2.next = mergeTwoLists(list2.next, list1)
        return list2
    }
}

//爬樓梯
func climbStairs(_ n: Int) -> Int {
    var p = 0, q = 0, r = 1
    var j = 1
    while j <= n {
        p = q
        q = r
        r = p + q
        
        j += 1
    }
    return r
}

//二叉樹(shù)的中序遍歷
func inorderTraversal(_ root: TreeNode?) -> [Int] {
    guard let root = root else { return [] }
    
    var notes: [Int] = []
    if root.left != nil {
        notes.append(contentsOf: inorderTraversal(root.left))
    }
    notes.append(root.val)
    if root.right != nil {
        notes.append(contentsOf: inorderTraversal(root.right))
    }
    return notes
}

//對(duì)稱(chēng)二叉樹(shù)
func isSymmetric(_ root: TreeNode?) -> Bool {
    func check(left: TreeNode?, right: TreeNode?) -> Bool {
        if left == nil && right == nil { return true }
        if left == nil || right == nil { return false }
        
        return left?.val == right?.val &&
               check(left: left?.left, right: right?.right) &&
               check(left: left?.right, right: right?.left)
    }
    return check(left: root, right: root)
}

//買(mǎi)賣(mài)股票的最佳時(shí)機(jī)
func maxProfit(_ prices: [Int]) -> Int {
    var minPrice = Int.max
    var maxProfit = 0
    for price in prices {
        if price < minPrice {
            minPrice = price
        }
        maxProfit = max(maxProfit, price-minPrice)
    }
    return maxProfit
}

//只出現(xiàn)一次的數(shù)字
//給你一個(gè) 非空 整數(shù)數(shù)組 nums 众辨,除了某個(gè)元素只出現(xiàn)一次以外驹饺,其余每個(gè)元素均出現(xiàn)兩次。找出那個(gè)只出現(xiàn)了一次的元素
func singleNumber(_ nums: [Int]) -> Int {
    var dict: [Int: Int] = [:]
    for num in nums {
        if let res = dict[num] {
            dict[num] = res + 1
        } else {
            dict[num] = 1
        }
    }
    return dict.sorted { $0.value < $1.value }.first?.key ?? 0
    
//    var res = 0
//    for num in nums {
//        res ^= num
//    }
//    return res
}

//鏈表是否有環(huán)
func hasCycle(_ head: ListNode?) -> Bool {
    if head == nil || head?.next == nil {
        return false
    }
    
    
    var slow = head, fast = head?.next
    while slow !== fast {
        if fast == nil || fast?.next == nil {
            return false
        }
        slow = slow?.next
        fast = fast?.next?.next
    }
    return true
}

//相交鏈表
func getIntersectionNode(_ headA: ListNode?, _ headB: ListNode?) -> ListNode? {
    var pA = headA, pB = headB
    if pA == nil || pB == nil { return nil }
    while pA !== pB {
        pA = pA == nil ? headB : pA?.next
        pB = pB == nil ? headA : pB?.next
    }
    return pA
}

//反轉(zhuǎn)鏈表
func reverseList(_ head: ListNode?) -> ListNode? {
    if head == nil || head?.next == nil { return head }
    var head = head
    var p1: ListNode? = nil
    var p2 = head
    while head != nil {
        p2 = p2?.next
        head?.next = p1
        p1 = head
        head = p2
    }
    return p1
}

//翻轉(zhuǎn)二叉樹(shù)
func invertTree(_ root: TreeNode?) -> TreeNode? {
    if root == nil { return nil }
    let right = root?.right
    let left = root?.left
    root?.left = invertTree(right)
    root?.right = invertTree(left)
    return root
}

//合并二叉樹(shù)
func mergeTrees(_ root1: TreeNode?, _ root2: TreeNode?) -> TreeNode? {
    guard let root1 = root1 else { return root2 }
    guard let root2 = root2 else { return root1 }
    let root = TreeNode(root1.val + root2.val)
    root.left = mergeTrees(root1.left, root2.left)
    root.right = mergeTrees(root1.right, root2.right)
    return root
}

//二叉樹(shù)的直徑
//給定一棵二叉樹(shù)旁蔼,你需要計(jì)算它的直徑長(zhǎng)度礁遵。一棵二叉樹(shù)的直徑長(zhǎng)度是任意兩個(gè)結(jié)點(diǎn)路徑長(zhǎng)度中的最大值院领。這條路徑可能穿過(guò)也可能不穿過(guò)根結(jié)點(diǎn)
//思路: 把每一個(gè)結(jié)點(diǎn)當(dāng)成根節(jié)點(diǎn) 得到其 左子樹(shù)深度+右子樹(shù)深度+1东囚, 然后取這些值的最大值 就是二叉樹(shù)的直徑
func diameterOfBinaryTree(_ root: TreeNode?) -> Int {
    var res = 0
    
    func maxDepth(_ root: TreeNode?) -> Int {
        guard let root = root else { return 0 }
        return 1 + max(maxDepth(root.left), maxDepth(root.right))
    }
    
    func maxNotes(_ root: TreeNode?) {
        guard let root = root else { return }
        let l = maxDepth(root.left)
        let r = maxDepth(root.right)
        res = max(res, l + r)
        maxNotes(root.left)
        maxNotes(root.right)
    }
    
    maxNotes(root)
    return res
}

//刪除鏈表的倒數(shù)第 N 個(gè)結(jié)點(diǎn)
func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
    if n <= 0 { return head }
    let preHead: ListNode? = ListNode(0, head)
    var p = preHead, q = head
    for _ in 0..<n {
        q = q?.next
    }
    while q != nil {
        p = p?.next
        q = q?.next
    }
    p?.next = p?.next?.next
    return preHead?.next
}

//二叉樹(shù)展開(kāi)為鏈表(按照前序遍歷順序)
func flatten(_ root: TreeNode?) {
    if root == nil { return }
    var p = root
    if p?.left != nil {
        p = p?.left
        while p?.right != nil {
            p = p?.right
        }
        p?.right = root?.right
        root?.right = root?.left
        root?.left = nil
    }
    flatten(root?.right)
}

//給定一個(gè)二叉樹(shù)之剧,找出其最小深度郭卫。
//最小深度是從根節(jié)點(diǎn)到最近葉子節(jié)點(diǎn)的最短路徑上的節(jié)點(diǎn)數(shù)量。
//說(shuō)明:葉子節(jié)點(diǎn)是指沒(méi)有子節(jié)點(diǎn)的節(jié)點(diǎn)背稼。
func minDepth(_ root: TreeNode?) -> Int {
    guard let root = root else { return 0 }
    let m1 = minDepth(root.left)
    let m2 = minDepth(root.right)
    return root.left == nil || root.right == nil ? 1 + m1 + m2 : 1 + min(m1, m2)
}

//給定一個(gè)二叉樹(shù)贰军,找出其最大深度。
func maxDepth(_ root: TreeNode?) -> Int {
      guard let root = root else { return 0 }
      return 1 + max(maxDepth(root.left), maxDepth(root.right))
}

//二叉樹(shù)的層序遍歷
func levelOrder(_ root: TreeNode?) -> [[Int]] {
    if root == nil { return [] }
    var res: [[Int]] = []
    var arr: [TreeNode?] = [root]
    while !arr.isEmpty {
        let count = arr.count
        var temps: [Int] = []
        for _ in 0..<count {
            let node = arr.removeFirst()
            temps.append(node!.val)
            
            if node?.left != nil {
                arr.append(node?.left)
            }
            if node?.right != nil {
                arr.append(node?.right)
            }
        }
        res.append(temps)
    }
    return res
}

//驗(yàn)證二叉搜索樹(shù)
// 左子樹(shù) < 根節(jié)點(diǎn) < 右子樹(shù)
func isValidBST(_ root: TreeNode?) -> Bool {
    func isValidBST(_ note: TreeNode?, min: Int, max: Int) -> Bool {
        if note == nil { return true }
        let value = note!.val
        if value <= min || value >= max {
            return false
        }
        return isValidBST(note?.left, min: min, max: value) &&
               isValidBST(note?.right, min: value, max: max)
    }
    return isValidBST(root, min: Int.min, max: Int.max)
}

// 斐波那契數(shù)列
func fib(_ n: Int) -> Int {
    if n < 2 { return n }
    var p = 0, q = 0, r = 1
    for _ in 2...n {
        p = q
        q = r
        r = (p + q) % 1_000_000_007
    }
    return r
}

//func hash(into hasher: inout Hasher)
//static func == (lhs: Self, rhs: Self) -> Bool
extension Array where Element: Hashable {
    func removingDuplicates() -> [Element] {
        var addedDict = [Element: Bool]()

        return filter {
            addedDict.updateValue(true, forKey: $0) == nil
        }
    }

    mutating func removeDuplicates() {
        self = self.removingDuplicates()
    }
}

// 快排
func quickSort<T: Comparable>(list: inout [T], start: Int, end: Int) {
    if start >= end { return }
    
    let index = partition(list: &list, start: start, end: end)
    
    quickSort(list: &list, start: start, end: index-1)
    quickSort(list: &list, start: index+1, end: end)
}
func partition<T: Comparable>(list: inout [T], start: Int, end: Int) -> Int {
    var left = start, right = end
    let temp = list[start]
    while left != right {
        while list[right] >= temp, left < right {
            right -= 1
        }
        while list[left] <= temp, left < right {
            left += 1
        }
        if left < right {
            list.swapAt(left, right)
        }
    }
    list.swapAt(left, start)
    return left
}

//二分插入法排序
func binarySort<T: Comparable>(array: inout [T]) {
    if array.count <= 1 { return }
        
    var low, mid, high: Int
    var base: T
    
    for i in 1...array.count - 1 {
        low = 0
        high = i - 1
        base = array[i]

        while low <= high {
            mid = (low + high) / 2
            if base <= array[mid] { // 升序
                high = mid - 1
            } else {
                low = mid + 1
            }
        }
        
        var j = i - 1
        while j >= high + 1 {
            array[j + 1] = array[j]
            j -= 1
        }
        
        array[high + 1] = base;
    }
}

// 冒泡
func bubblingSort(list: inout [Int]) {
    let count = list.count
    if list.count <= 1 { return }
    for i in 0..<count - 1 {
        for j in 0..<count - 1 - i {
            if list[j] > list[j+1] {
                list.swapAt(j, j+1)
            }
        }
    }
}

///【雙指針】刪除重復(fù)項(xiàng)
func removeDuplicates(_ nums: inout [Int]) -> Int {
    let count = nums.count
    if count <= 1 { return count }
    var p = 0, q = 1
    while q < count {
        if nums[p] == nums[q] {
            q += 1
        } else {
            nums[p+1] = nums[q]
            p += 1
            q += 1
        }
    }
    return p + 1
}
//鏈表操作的兩種方式:
//1. 直接使用原來(lái)的鏈表來(lái)進(jìn)行操作蟹肘。
//2. 設(shè)置一個(gè)虛擬頭結(jié)點(diǎn)在進(jìn)行操作词疼。
//刪除鏈表元素
func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? {
    let dummyNode = ListNode()
    dummyNode.next = head
    var currentNode = dummyNode
    while let curNext = currentNode.next {
        if curNext.val == val {
            currentNode.next = curNext.next
        } else {
            currentNode = curNext
        }
    }
    return dummyNode.next
}

//兩兩交換鏈表中的節(jié)點(diǎn)
func swapPairs(_ head: ListNode?) -> ListNode? {
    if head == nil || head?.next == nil {
        return head
    }
    let dummyHead: ListNode = ListNode(-1, head)
    var current: ListNode? = dummyHead
    while current?.next != nil && current?.next?.next != nil {
        let temp1 = current?.next
        let temp2 = current?.next?.next?.next
        
        current?.next = current?.next?.next
        current?.next?.next = temp1
        current?.next?.next?.next = temp2
        
        current = current?.next?.next
    }
    return dummyHead.next
}

//二叉樹(shù)的最近公共祖先
func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
        guard let root = root else { return nil }
        if root === p || root === q { return root }
    
        let left  = lowestCommonAncestor(root.left,  p, q)
        let right = lowestCommonAncestor(root.right, p, q)

        if left != nil, right != nil { return root }

        return left ?? right
}

//多讀單寫(xiě)
http://www.reibang.com/p/711859ed2ef3
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市帘腹,隨后出現(xiàn)的幾起案子贰盗,更是在濱河造成了極大的恐慌,老刑警劉巖阳欲,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舵盈,死亡現(xiàn)場(chǎng)離奇詭異陋率,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)秽晚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)瓦糟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人赴蝇,你說(shuō)我怎么就攤上這事菩浙。” “怎么了句伶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵劲蜻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我熄阻,道長(zhǎng)斋竞,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任秃殉,我火速辦了婚禮坝初,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钾军。我一直安慰自己鳄袍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布吏恭。 她就那樣靜靜地躺著拗小,像睡著了一般。 火紅的嫁衣襯著肌膚如雪樱哼。 梳的紋絲不亂的頭發(fā)上哀九,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音搅幅,去河邊找鬼阅束。 笑死,一個(gè)胖子當(dāng)著我的面吹牛茄唐,可吹牛的內(nèi)容都是我干的息裸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼沪编,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呼盆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蚁廓,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤访圃,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后相嵌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體腿时,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡克胳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了圈匆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漠另。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖跃赚,靈堂內(nèi)的尸體忽然破棺而出笆搓,到底是詐尸還是另有隱情,我是刑警寧澤纬傲,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布满败,位于F島的核電站,受9級(jí)特大地震影響叹括,放射性物質(zhì)發(fā)生泄漏算墨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一汁雷、第九天 我趴在偏房一處隱蔽的房頂上張望净嘀。 院中可真熱鬧,春花似錦侠讯、人聲如沸挖藏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)膜眠。三九已至,卻和暖如春溜嗜,著一層夾襖步出監(jiān)牢的瞬間宵膨,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工炸宵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辟躏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓焙压,卻偏偏與公主長(zhǎng)得像鸿脓,于是被迫代替她去往敵國(guó)和親抑钟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涯曲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容