一条语句的重复执行次数称作语句频度( Frequency Count) 由于语句的执行要由源程序经编译程序翻译成目标代码,目标代码经装配再执行,因此语句执行一次实际所需的具体时间是与机器的软、硬件环境(如机器速度、编译程序质量等)密切相关的。所以,所谓的算法分析并非精确统计算法实际执行所需时间,而是针对算法中语句的执行次数做出估计,从中得到算法执行时间的信息。 设每条语句执行一次所需的时间均是单位时间,则一个算法的执行时间可用该算法中所有语句频度之和来度量。
funcfirstUniqChar(_s: String) -> Int { var dic =Dictionary<Character, Int>() for (i,value) in s.enumerated() { if dic.keys.contains(value) { dic[value] =-1 } else { dic[value] = i } } for (i,value) in s.enumerated() { if dic[value] == i { return i } } return-1 }
classSolution_3{ publicclassListNode{ publicvar val: Int publicvar next: ListNode? publicinit(_val: Int) { self.val = val self.next =nil } } funcreverseKGroup(_head: ListNode?, _k: Int) -> ListNode? { guard head !=nil&& k >1else { return head } let dummy:ListNode? =ListNode.init(-1) dummy?.next = head var pre = dummy var end = dummy while (end?.next !=nil) { for_in0..<k { end = end?.next } if (end ==nil) { break } let start = pre?.next let next = end?.next end?.next =nil pre?.next = reverse(start) start?.next = next pre = start end = pre } return dummy?.next } privatefuncreverse(_pre: ListNode?) -> ListNode? { var pre = pre var node = pre?.next while node !=nil { let next = node?.next node?.next = pre pre = node node = next } return pre } }
classSolution_4{ publicclassListNode{ publicvar val: Int publicvar next: ListNode? publicinit(_val: Int) { self.val = val self.next =nil } } funcrotateRight(_head: ListNode?, _k: Int) -> ListNode? { guard k >0&& head !=nilelse { return (k ==0? head:nil) } let dummy: ListNode? =ListNode.init(-1) dummy?.next = head var keyPre = dummy var end = dummy var i =1 while end?.next?.next !=nil { end = end?.next i +=1 } guard i != k else { return head } i = (k<i ? i-k:i-k%i) for_in1...i { keyPre = keyPre?.next } end?.next?.next = dummy?.next let res = keyPre?.next keyPre?.next =nil return res } }
复制带随机指针的链表 - 中等
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。
我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
funclengthOfLongestSubstring(_s: String) -> Int { var left =0 var len =0 var dic = [Character: Int]() for (i,char) in s.enumerated() { let index = dic[char] dic[char] = i if index !=nil&& index!>= left { left = index!+1 } if i - left +1> len { len = i - left +1 } } return len }
盛最多水的容器 - 中等
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。 示例: 输入:[1,8,6,2,5,4,8,3,7] 输出:49
funcmaxArea(_height: [Int]) -> Int { guard height.count >1else { return0 } var res =0 var left =0 var right = height.count-1 while right > left { let temp =min(height[left], height[right])*(right-left) if temp > res { res = temp } if height[left] < height[right] { left +=1 } else { right -=1 } } return res }
三数之和 - 中等
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
functhreeSum(_nums: [Int]) -> [[Int]] { guard nums.count >2else { return [] } let nums = nums.sorted() guard nums.first!<=0else { return [] } var res = [[Int]]() for i in0..<nums.count -2 { if i >0&& nums[i] == nums[i -1] { continue } var left = i +1 var right = nums.count -1 while left < right { let temp = nums[left]+nums[right]+nums[i] if temp ==0 { res.append([nums[i], nums[left], nums[right]]) repeat { left +=1 } while left < right && nums[left] == nums[left-1] repeat { right -=1 } while left < right && nums[right] == nums[right+1] } elseif temp <0 { repeat { left +=1 } while left < right && nums[left] == nums[left-1] } else { repeat { right -=1 } while left < right && nums[right] == nums[right+1] } } } return res }
functhreeSumClosest(_nums: [Int], _target: Int) -> Int { guard nums.count >2else { return0 } let nums = nums.sorted() var res = nums[0]+nums[1]+nums[2] guard res != target else { return res } for i in0..<nums.count -2 { if i >0&& nums[i] == nums[i-1] { continue } var left = i +1 var right = nums.count -1 while left < right { let temp = nums[left]+nums[right]+nums[i] guard temp != target else { return target } ifabs(target-temp) <abs(target-res) { res = temp } if temp > target { repeat { right -=1 } while left < right && nums[right] == nums[right+1] } else { repeat { left +=1 } while left < right && nums[left] == nums[left-1] } } } return res }
funcremoveDuplicates(_nums: inout [Int]) -> Int { guard nums.count >1else { return nums.count } var c =0 for i in1..<nums.count { if nums[i] != nums[c] { c +=1 nums[c] = nums[i] } } return c+1 }
funcmaxProfit(_prices: [Int]) -> Int { guard prices.count >1else { return0 } var money =0 var min =Int.max for i in0..<prices.count { if prices[i] < min { min = prices[i] } if prices[i] - min > money { money = prices[i] - min } } return money }
长度最小的子数组 - 中等
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
funcminSubArrayLen(_s: Int, _nums: [Int]) -> Int { var res =Int.max var left =0 var sum =0 for (i, value) in nums.enumerated() { sum += value while sum >= s { res =min(res, i-left+1) sum -= nums[left] left +=1 } } return res ==Int.max ?0:res }
publicclassListNode{ publicvar val: Int publicvar next: ListNode? publicinit(_val: Int) { self.val = val self.next =nil } }
classSolution_6{ funchasCycle(_head: ListNode?) -> Bool { var slow = head var fast = head while fast?.next !=nil { slow = slow?.next fast = fast?.next?.next if fast == slow { returntrue } } returnfalse } }
fileprivatefuncbitSquareSum(_n: Int) -> Int { var n = n var sum =0 while n >0 { let bit = n%10 sum += bit*bit n = n/10 } return sum }
funcisHappy(_n: Int) -> Bool { var slow = n var fast = n repeat { slow = bitSquareSum(slow) fast = bitSquareSum(fast) fast = bitSquareSum(fast) } while slow != fast return slow ==1 }
链表的中间结点 - 简单
给定一个带有头结点 head 的非空单链表,返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。
funcmiddleNode(_head: ListNode?) -> ListNode? { var slow = head var fast = head while fast?.next !=nil { slow = slow?.next fast = fast?.next?.next } return slow }
字符串操作
z字形转换 - 中等
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下: L C I R E T O E S I I G E D H N
funcconvert(_s: String, _numRows: Int) -> String { guard numRows >1&& s.count > numRows else { return s } var list = [String].init(repeating: "", count: numRows) var c =0 var x = numRows*2-2 for (i, value) in s.enumerated() { var r = (i-c)%(x) if r == x-1 { c += x } if r >= numRows { r = x-r } list[r] +=String(value) } var res ="" for s in list { res += s } return res }
funclongestCommonPrefix(_strs: [String]) -> String { guard strs.count >1else { return strs.first ??"" } let strs = strs.sorted() var index =0 let first = strs.first! for (i, value) in first.enumerated() { for (j, str) in strs[1..<strs.count].enumerated() { if value == str[String.Index.init(utf16Offset: i, in: str)] { if j == strs.count-2 { index +=1 } } else { return index ==0?"":String(first.prefix(index)) } } } returnString(first.prefix(index)) }
funcreverse(_x: Int) -> Int { var num = x var res =0 while num !=0 { res = res*10+ num%10 num = num/10 } guardabs(res) <=Int32.max else { return0 } return res }
funcmyAtoi(_str: String) -> Int { let str = str.trimmingCharacters(in: .whitespaces) guard str.count >0else { return0 } var res ="" for value in str { if value.isNumber { res +=String(value) } elseif value =="-"|| value =="+" { guard res ==""else { break } res +=String(value) } else { break } } guard res !=""&& res !="-"&& res !="+"else { return0 } let ans =Int32(res) guardlet x = ans else { if res.first!.isNumber { returnInt(Int32.max) } else { return res.first!=="+"?Int(Int32.max):Int(Int32.min) } } returnInt(x) }
funcspiralOrder(_matrix: [[Int]]) -> [Int] { var matrix = matrix var isReversed =false var res = [Int]() while!matrix.isEmpty { if!isReversed { res += matrix.removeFirst() if (matrix.first ==nil) { break } for i in0..<matrix.count { res.append(matrix[i].removeLast()) } if matrix.first!.isEmpty { break } isReversed =true } else { res += matrix.removeLast().reversed() if (matrix.first ==nil) { break } for i in (0..<matrix.count).reversed() { res.append(matrix[i].removeFirst()) } if matrix.first!.isEmpty { break } isReversed =false } } return res }
矩阵置零 - 中等
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用 原地 算法。
funcsetZeroes(_matrix: inout [[Int]]) { var zeroRow =false var zeroColumn =false for y in0..< matrix.count { for x in0..< matrix[y].count { if matrix[y][x] ==0 { if y ==0 { zeroRow =true } if x ==0 { zeroColumn =true } matrix[0][x] =0 matrix[y][0] =0 } } } for x in0..< matrix[0].count { if matrix[0][x] ==0&& x !=0 { for y in0..< matrix.count { matrix[y][x] =0 } } } for y in0..< matrix.count { if matrix[y][0] ==0&& y !=0 { for x in0..< matrix[y].count { matrix[y][x] =0 } } } if zeroRow { for x in0..< matrix[0].count { matrix[0][x] =0 } } if zeroColumn { for y in0..< matrix.count { matrix[y][0] =0 } } }
这道题为了输出子集,势必时间复杂度为n2^n,空间复杂度为n2^n。主要我们要想怎么得到子集并且不能重复。这里我们使用二进制来解决问题。听起来两者表面没什么关系,但是子集的个数是2^n。对应了n位的二进制数。将每个子集映射到长度为 n 的位掩码中,其中第 i 位掩码 nums[i] 为 1,表示第 i 个元素在子集中;如果第 i 位掩码 nums[i] 为 0,表示第 i 个元素不在子集中。按照这样的思想我们就能很轻松的求出子集。
funcfindUnsortedSubarray(_nums: [Int]) -> Int { var minValue =Int.max var maxValue =Int.min for i in1..<nums.count { if nums[i] < nums[i-1] { minValue =min(minValue,nums[i]) } } for i in (0..<nums.count-1).reversed() { if nums[i] > nums[i+1] { maxValue =max(maxValue, nums[i]) } } var left =0 var right = nums.count-1 while left < nums.count { if minValue < nums[left] { break } left +=1 } while right >=0 { if maxValue > nums[right] { break } right -=1 } return right < left ?0:right-left+1 }
funccanMakeArithmeticProgression(_arr: [Int]) -> Bool { guard arr.count >2else { returntrue } var minValue =Int.max var maxValue =Int.min var dic =Dictionary<Int,Int>() for num in arr { dic[num] = (dic[num] !=nil) ? dic[num]!+1:1 if minValue > num { minValue = num } if maxValue < num { maxValue = num } } guard dic.keys.count == arr.count else { return dic.keys.count ==1?true:false } guard (maxValue-minValue)%(arr.count-1) ==0else { returnfalse } let d = (maxValue-minValue)/(arr.count-1) for num in arr { if (num-minValue)%d !=0 { returnfalse } } returntrue }
你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
classMyQueue{ privateclassStack{ privatevar elements = [Int]() /** Push element x to the back of queue. */ funcpush(_x: Int) { elements.append(x) } /** Removes the element from in front of queue and returns that element. */ funcpop() -> Int { return elements.popLast()! } /** Get the front element. */ funcpeek() -> Int { return elements.last! } /** Returns whether the queue is empty. */ funcempty() -> Bool { return elements.isEmpty } } privatevar stack1 =Stack() privatevar stack2 =Stack() /** Initialize your data structure here. */ init() {
} /** Push element x to the back of queue. */ funcpush(_x: Int) { stack1.push(x) } /** Removes the element from in front of queue and returns that element. */ funcpop() -> Int { if stack2.empty() { while!stack1.empty() { stack2.push(stack1.pop()) } } return stack2.pop() } /** Get the front element. */ funcpeek() -> Int { if stack2.empty() { while!stack1.empty() { stack2.push(stack1.pop()) } } return stack2.peek() } /** Returns whether the queue is empty. */ funcempty() -> Bool { return stack1.empty() && stack2.empty() } }
注意: 你只能使用队列的基本操作– 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
classMyStack{ privateclassQueue{ privatevar elements = [Int]() /** Push element x onto stack. */ funcenqueue(_x: Int) { elements.append(x) } /** Removes the element on top of the stack and returns that element. */ funcdequeue() -> Int { return elements.removeFirst() } /** Get the top element. */ functop() -> Int { return elements.first! } /** Returns whether the stack is empty. */ funcempty() -> Bool { return elements.isEmpty } funcsize() -> Int { return elements.count } } privatevar queue1 =Queue() privatevar queue2 =Queue() privatevar topValue =0
/** Initialize your data structure here. */ init() {
} /** Push element x onto stack. */ funcpush(_x: Int) { queue1.enqueue(x) topValue = x } /** Removes the element on top of the stack and returns that element. */ funcpop() -> Int { while queue1.size() >1 { topValue = queue1.dequeue() queue2.enqueue(topValue) } let res = queue1.dequeue() queue1 = queue2 queue2 =Queue() return res } /** Get the top element. */ functop() -> Int { return topValue } /** Returns whether the stack is empty. */ funcempty() -> Bool { return queue1.empty() && queue2.empty() } }
这道题看上去用字典解决就可以直接得到答案,但是这里有保证字典序最小的要求,情况就要复杂得多。 首先要知道什么叫 “字典序”。字符串之间比较跟数字之间比较是不太一样的。字符串比较是从头往后一个字符一个字符比较的。哪个字符串大取决于两个字符串中 第一个对应不相等的字符 。根据这个规则,任意一个以 a 开头的字符串都大于任意一个以 b 开头的字符串。 按照这个要求,我们可以想到用栈来实现这样的过程。对字符串进行遍历,并选择入栈还是出栈 * 如果栈里已经存在,则忽略(只存在一个元素) * 如果比栈顶元素字典序小,且栈顶元素在后面还会出现,则出栈 * 否则,入栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
funcremoveDuplicateLetters(_s: String) -> String { var stack = [Character]() var lastAppearIndexDic = [Character:Int]() varset= [Character:Bool]() // 为了减低时间复杂度,提前求出元素出现的最后一个位置 for (i, c) in s.enumerated() { lastAppearIndexDic[c] = i } for (i, c) in s.enumerated() { guard!(set[c] ??false) else { continue } // 栈里已经有直接跳过 whilelet top = stack.last, top > c, lastAppearIndexDic[top]!>= i { let poped = stack.popLast()! set[poped] =false } stack.append(c) set[c] =true } returnString(stack) }
堆相关
数组中的第K个最大元素 - 中等
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
if!elements.isEmpty { for i instride(from: elements.count/2-1, through: 0, by: -1) { siftDown(from: i) } } }
mutatingfuncsiftDown(fromindex: Int) { var parent = index whiletrue { let left = leftIndex(of: parent) let right = rightIndex(of: parent) var candidate = parent if left < count && sort(elements[left], elements[candidate]) { candidate = left } if right < count && sort(elements[right], elements[candidate]) { candidate = right } if candidate == parent { return } elements.swapAt(parent, candidate) parent = candidate } }
mutatingfuncsiftUp(fromindex: Int) { var child = index var parent = parentIndex(of: child) while child >0&& sort(elements[child], elements[parent]) { elements.swapAt(child, parent) child = parent parent = parentIndex(of: child) } }
funcleftIndex(ofindex: Int) -> Int { return (2* index) +1 }
funcrightIndex(ofindex: Int) -> Int { return (2* index) +2 }
funcparentIndex(ofindex: Int) -> Int { return (index -1) /2 } } funcfindKthLargest(_nums: [Int], _k: Int) -> Int { var heap =Heap.init(sort: >) for num in nums { heap.push(num) if heap.count > k { heap.pop() } } return heap.pop()! } }
前k个高频元素 - 中等
给定一个非空的整数数组,返回其中出现频率前 k高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。 你可以按任意顺序返回答案。
if!elements.isEmpty { for i instride(from: elements.count/2-1, through: 0, by: -1) { siftDown(from: i) } } }
mutatingfuncsiftDown(fromindex: Int) { var parent = index whiletrue { let left = leftIndex(of: parent) let right = rightIndex(of: parent) var candidate = parent if left < count && sort(elements[left].value, elements[candidate].value) { candidate = left } if right < count && sort(elements[right].value, elements[candidate].value) { candidate = right } if candidate == parent { return } elements.swapAt(parent, candidate) parent = candidate } }
mutatingfuncsiftUp(fromindex: Int) { var child = index var parent = parentIndex(of: child) while child >0&& sort(elements[child].value, elements[parent].value) { elements.swapAt(child, parent) child = parent parent = parentIndex(of: child) } }
Find a path to success 有没有解 Find all paths to success 求所有解 求所有解的个数 求所有解的具体信息 Find the best path to success 求最优解 回溯法是一个剪枝了的二叉树。我们要得到的结果是可以 good leaf,如果不满足 good leaf 就继续向下搜索,搜索的时候需要满足一定的条件。
funccombinationSum2(_candidates: [Int], _target: Int) -> [[Int]] { var res = [[Int]]() if candidates.isEmpty { return res } let arr = candidates.sorted() var path = [Int]() helper_combinationSum2(arr, target, 0, &path, &res) return res }
fileprivatefunchelper_combinationSum2(_candidates: [Int], _target: Int, _begin: Int, _path: inout [Int], _res: inout [[Int]]) { if target ==0 { res.append(path) return } for i in begin..<candidates.count { if target-candidates[i] <0 { break } if i > begin && candidates[i] == candidates[i-1] { continue } path.append(candidates[i]) helper_combinationSum2(candidates, target-candidates[i], i+1, &path, &res) path.removeLast() } }