数
- 巧用位运算符号,例如只出现一次的数字
func singleNumber(_ nums: [Int]) -> Int { //通过位运算 var rs = 0 for num in nums { rs = rs ^ num } return rs }
字符串
- 巧用栈的思想去解决问题 例如棒球比赛
func calPoints(_ ops: [String]) -> Int { var rs: [Int] = [] for s in ops { switch s { case "C": rs.removeLast() case "D": rs.append((rs.last ?? 0) * 2) case "+": let p = rs.last ?? 0 rs.removeLast() let pp = rs.last ?? 0 rs.append(p) rs.append(p + pp) default: rs.append(Int(s)!) } } return rs.reduce(0, {$0 + $1}) } 当然还可以更进一步优化,在每一步进行计算得分,栈的结构只是用来完成"C"、"D"、"+"等操作,这样就可以去掉最后对数组的reduce - 利用ascii,例如特殊等价字符串组
func numSpecialEquivGroups(_ A: [String]) -> Int { var rs: Set<String> = Set() for a in A { let t = Array(a) var tmp: [Int] = Array(repeating: 0, count: 52) for i in 0..<t.count { let ascii = UnicodeScalar(String(t[i]))!.value tmp[Int(ascii) - 97 + 26 * (i % 2)] += 1 } //tmp数组转字符串 rs.insert(tmp.reduce("", {$0 + "\($1)"})) } return rs.count }
数组
- 动态规划的思想,例如杨辉三角
func generate(_ numRows: Int) -> [[Int]] { if numRows == 0 { return [] } if numRows == 1 { return [[1]] } if numRows == 2 { return [[1],[1,1]] } var rs: [[Int]] = [[1],[1,1]] for i in 3...numRows { var r: [Int] = [] r.append(1) for j in 1..<i-1 { r.append(rs[i-2][j-1] + rs[i-2][j]) } r.append(1) rs.append(r) } return rs } - 计数排序及其变种,例如数组的相对顺序
func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { var tmp: [Int] = Array(repeating: 0, count: 1001) var rs: [Int] = [] //计数 for i in 0..<arr1.count { tmp[arr1[i]] += 1 } //按照arr2中的顺序排序 for i in 0..<arr2.count { while tmp[arr2[i]] > 0 { rs.append(arr2[i]) tmp[arr2[i]] -= 1 } } //排序不存在arr2中的,因为tmp数组的下标就是数值,所以直接遍历 for i in 0..<1001 { while tmp[i] > 0 { rs.append(i) tmp[i] -= 1 } } return rs } - 利用hash表加快查表的效率,例如拼写单词
func countCharacters(_ words: [String], _ chars: String) -> Int { var searchKey: [Character: Int] = [:] //创建对应表 for c in chars { searchKey.updateValue((searchKey[c] ?? 0) + 1, forKey: c) } var rs = 0 for word in words { var tmp = searchKey var count = 0 for w in word { if tmp.keys.contains(w) { var value = tmp[w]! value -= 1 if value == 0 { tmp.removeValue(forKey: w) } else { tmp.updateValue(value, forKey: w) } count += 1 } else { count = 0 break } } rs += count } return rs }
链表
- 快慢指针,可以快速找到未知长度的链表的中间节点,例如链表的中间节点,也可以通过快慢指针的方式判断链表内是否有环
func middleNode(_ head: ListNode?) -> ListNode? { var fast = head var slow = head while slow?.next != nil && fast?.next != nil { slow = slow?.next fast = fast?.next?.next } return slow }
树
- 二叉搜索树
- 递归的方式去完成二叉搜索树的操作,例如修剪二叉搜索树
func trimBST(_ root: TreeNode?, _ L: Int, _ R: Int) -> TreeNode? { guard let root = root else { return nil } if root.val < L { return trimBST(root.right, L, R) } else if root.val > R { return trimBST(root.left, L, R) } root.left = trimBST(root.left, L, R) root.right = trimBST(root.right, L, R) return root } - 深度优先
- 先序遍历叶子相似的树
//叶子相似的树 func leafSimilar(_ root1: TreeNode?, _ root2: TreeNode?) -> Bool { var leaves1: [Int] = [] var leaves2: [Int] = [] _leaves(root1, &leaves1) _leaves(root2, &leaves2) return leaves1.elementsEqual(leaves2) } fileprivate func _leaves(_ root: TreeNode?, _ leaves: inout [Int]) { guard let root = root else { return } if root.left == nil && root.right == nil { leaves.append(root.val) } _leaves(root.left, &leaves) _leaves(root.right, &leaves) } - 中序遍历递增顺序查找树
static var rs: TreeNode? func increasingBST(_ root: TreeNode?) -> TreeNode? { Solution.rs = TreeNode(0) let t = Solution.rs _increasingBST(root) return t?.right } fileprivate func _increasingBST(_ root: TreeNode?) { guard let root = root else { return } _increasingBST(root.left) let node: TreeNode = TreeNode(root.val) Solution.rs?.right = node Solution.rs = node _increasingBST(root.right) } - 后序遍历
- 广度优先 例如二叉树的层平均值
func averageOfLevels(_ root: TreeNode?) -> [Double] { var rs: [Double] = [] guard let root = root else { return rs } //利用数组完成队列操作 var queue: [TreeNode] = [root] //层序遍历 + 队列 while !queue.isEmpty { //子节点数量 let nodeCount = queue.count var sum = 0 for i in 0..<nodeCount { let firstNode = queue.first! sum += firstNode.val queue.removeFirst() if let left = firstNode.left { queue.append(left) } if let right = firstNode.right { queue.append(right) } } rs.append(Double(sum)/Double(nodeCount)) } return rs }
栈
- 单调递增、递减栈下一个更大元素 I
func nextGreaterElement(_ nums1: [Int], _ nums2: [Int]) -> [Int] { //递减栈,使用简单数组实现 var decreaseStack: [Int] = [] //hash表,加快查找效率,使用简单字典实现 var hashTable: [Int: Int] = [:] //遍历nums2,维护递减栈 for i in 0..<nums2.count { if decreaseStack.count == 0 { //如果为空,则压入 decreaseStack.append(nums2[i]) } else { //遍历栈 while decreaseStack.count > 0 && decreaseStack.last! < nums2[i] { //维护字典,并将栈底弹出 hashTable.updateValue(nums2[i], forKey: decreaseStack.last!) decreaseStack.removeLast() } decreaseStack.append(nums2[i]) } } //遍历 num1,输出结果 var rs: [Int] = [] for i in 0..<nums1.count { rs.append(hashTable[nums1[i]] ?? -1) } return rs }
找规律
func minCostToMoveChips(_ chips: [Int]) -> Int {
var odd = 0
var even = 0
for i in chips {
if i % 2 == 0 {
even += 1
} else {
odd += 1
}
}
return min(even, odd)
}空间几何
func projectionArea(_ grid: [[Int]]) -> Int {
//从顶部看,面积为总共占有的格子数量
var top = 0
//从前面看,面积为每一行的最大数
var front = 0
//从侧面行,面积为每一列的最大数
var cArray: [Int] = Array(repeating: 0, count: 50)
for i in 0..<grid.count {
var tmpFront = 0
for j in 0..<grid[i].count {
tmpFront = max(tmpFront, grid[i][j])
if grid[i][j] != 0 {
top += 1
}
cArray[j] = max(cArray[j], grid[i][j])
}
front += tmpFront
}
let beside = cArray.reduce(0, {$0 + $1})
return top + front + beside
}持续更新ing...