├── .gitignore ├── README.md ├── main.go └── problem ├── 1.go ├── 101.go ├── 111.go ├── 114.go ├── 130.go ├── 141.go ├── 142.go ├── 147.go ├── 160.go ├── 179.go ├── 19.go ├── 2.go ├── 203.go ├── 213.go ├── 226.go ├── 23.go ├── 234.go ├── 236.go ├── 239.go ├── 26.go ├── 27.go ├── 295.go ├── 3.go ├── 310.go ├── 322.go ├── 347.go ├── 35.go ├── 355.go ├── 373.go ├── 392.go ├── 4.go ├── 424.go ├── 43.go ├── 472.go ├── 48.go ├── 5.go ├── 524.go ├── 53.go ├── 547.go ├── 56.go ├── 61.go ├── 63.go ├── 7.go ├── 713.go ├── 72.go ├── 75.go ├── 767.go ├── 84.go ├── 843.go ├── 85.go ├── 86.go ├── 93.go ├── 97.go └── 98.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LeetCodeInGo 2 | Practice Makes Perfect 3 | I leave no trace of wings in the air, but I am glad I have had my flight. 4 | 5 | |序号|题目名称|难度| 6 | |---| ----- | -------- | 7 | |[1](https://leetcode-cn.com/problems/two-sum/)|[两数之和](./problem/1.go)|Easy| 8 | |[2](https://leetcode-cn.com/problems/add-two-numbers/)|[两数相加](./problem/2.go)|Medium| 9 | |[3](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/)|[无重复字符的最长子串](./problem/3.go)|Medium| 10 | |[4](https://leetcode-cn.com/problems/median-of-two-sorted-arrays/)|[寻找两个有序数组的中位数](./problem/4.go)|Hard| 11 | |[5](https://leetcode-cn.com/problems/longest-palindromic-substring/)|[最长回文子串](./problem/5.go)|Medium| 12 | |[7](https://leetcode-cn.com/problems/reverse-integer/)|[整数反转](./problem/7.go)|Easy| 13 | |[19](https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/)|[删除链表的倒数第N个节点](./problem/19.go)|Medium| 14 | |[23](https://leetcode-cn.com/problems/merge-k-sorted-lists/)|[合并K个排序链表](./problem/23.go)|Hard| 15 | |[26](https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/)|[删除排序数组中的重复项](./problem/26.go)|Easy| 16 | |[27](https://leetcode-cn.com/problems/remove-element/)|[移除元素](./problem/27.go)|Easy| 17 | |[35](https://leetcode-cn.com/problems/search-insert-position/)|[搜索插入位置](./problem/35.go)|Easy| 18 | |[43](https://leetcode-cn.com/problems/multiply-strings/)|[字符串相乘](./problem/43.go)|Medium| 19 | |[48](https://leetcode-cn.com/problems/rotate-image/)|[旋转图像](./problem/48.go)|Medium| 20 | |[53](https://leetcode-cn.com/problems/multiply-strings/)|[最大子序和](./problem/53.go)|Easy| 21 | |[56](https://leetcode-cn.com/problems/merge-intervals/)|[合并区间](./problem/56.go)|Medium| 22 | |[61](https://leetcode-cn.com/problems/rotate-list/)|[旋转链表](./problem/61.go)|Medium| 23 | |[63](https://leetcode-cn.com/problems/unique-paths-ii/)|[不同路径 II](./problem/63.go)|Medium| 24 | |[72](https://leetcode-cn.com/problems/edit-distance/)|[编辑距离](./problem/72.go)|Hard| 25 | |[75](https://leetcode.com/problems/sort-colors/)|[颜色分类](./problem/75.go)|Medium| 26 | |[84](https://leetcode-cn.com/problems/largest-rectangle-in-histogram/)|[柱状图中最大的矩形](./problem/84.go)|Hard| 27 | |[85](https://leetcode-cn.com/problems/maximal-rectangle/)|[最大矩形](./problem/85.go)|Hard| 28 | |[86](https://leetcode.com/problems/partition-list/)|[分隔链表](./problem/86.go)|Medium| 29 | |[93](https://leetcode-cn.com/problems/restore-ip-addresses)|[复原IP地址](./problem/93.go)|Medium| 30 | |[97](https://leetcode-cn.com/problems/interleaving-string/comments/)|[交错字符串](./problem/97.go)|Medium| 31 | |[98](https://leetcode-cn.com/problems/validate-binary-search-tree/)|[验证二叉搜索树](./problem/98.go)|Medium| 32 | |[101](https://leetcode-cn.com/problems/symmetric-tree/)|[对称二叉树](./problem/101.go)|Easy| 33 | |[111](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/)|[二叉树的最小深度](./problem/111.go)|Easy| 34 | |[114](https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/)|[二叉树展开为链表](./problem/114.go)|Medium| 35 | |[130](https://leetcode-cn.com/problems/surrounded-regions/)|[被围绕的区域](./problem/130.go)|Medium| 36 | |[142](https://leetcode-cn.com/problems/linked-list-cycle-ii/)|[环形链表II](./problem/142.go)|Medium| 37 | |[147](https://leetcode-cn.com/problems/insertion-sort-list/)|[对链表进行插入排序](./problem/147.go)|Medium| 38 | |[160](https://leetcode-cn.com/problems/intersection-of-two-linked-lists/)|[相交链表](./problem/160.go)|Easy| 39 | |[179](https://leetcode-cn.com/problems/largest-number/)|[最大数](/problem/179.go)|Medium| 40 | |[203](https://leetcode-cn.com/problems/remove-linked-list-elements/)|[移除链表元素](./problem/203.go)|Easy| 41 | |[213](https://leetcode-cn.com/problems/house-robber-ii/)|[打家劫舍 II](./problem/213.go)|Medium| 42 | |[226](https://leetcode-cn.com/problems/invert-binary-tree/)|[翻转二叉树](./problem/226.go)|Easy| 43 | |[234](https://leetcode-cn.com/problems/palindrome-linked-list/)|[回文链表](./problem/234.go)|Easy| 44 | |[236](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/)|[二叉树的最近公共祖先](./problem/236.go)|Medium| 45 | |[239](https://leetcode-cn.com/problems/sliding-window-maximum/)|[滑动窗口最大值](./problem/239.go)|Hard| 46 | |[295](https://leetcode-cn.com/problems/find-median-from-data-stream/)|[数据流的中位数](./problem/295.go)|Hard| 47 | |[310](https://leetcode-cn.com/problems/minimum-height-trees/)|[最小高度树](./problem/310.go)|Medium| 48 | |[322](https://leetcode-cn.com/problems/coin-change/)|[零钱兑换](./problem/322.go)|Medium| 49 | |[347](https://leetcode-cn.com/problems/top-k-frequent-elements/)|[前k个高频元素](./problem/347.go)|Medium| 50 | |[355](https://leetcode-cn.com/problems/design-twitter/)|[设计推特](./problem/355.go)|Medium| 51 | |[373](https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums/)|[查找和最小的K对数字](./problem/373.go)|Medium| 52 | |[392](https://leetcode-cn.com/problems/is-subsequence/)|[判断子序列](./problem/392.go)|Medium| 53 | |[424](https://leetcode-cn.com/problems/longest-repeating-character-replacement/)|[替换后的最长重复字符](./problem/424.go)|Medium| 54 | |[524](https://leetcode-cn.com/problems/longest-word-in-dictionary-through-deleting/)|[通过删除字母匹配到字典里最长单词](./problem/524.go)|Medium| 55 | |[547](https://leetcode-cn.com/problems/friend-circles/)|[朋友圈](./problem/547.go)|Medium| 56 | |[713](https://leetcode-cn.com/problems/subarray-product-less-than-k/)|[乘积小于ķ的子数组](./problem/713.go)|Medium| 57 | |[767](https://leetcode-cn.com/problems/reorganize-string/)|[重构字符串](./problem/767.go)|Medium| 58 | |[843](https://leetcode-cn.com/problems/guess-the-word/)|[猜猜这个单词](./problem/843.go)|Hard| 59 | 60 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println("test here!") 9 | } 10 | -------------------------------------------------------------------------------- /problem/1.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。 5 | 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 6 | 7 | 示例: 8 | 给定 nums = [2, 7, 11, 15], target = 9 9 | 因为 nums[0] + nums[1] = 2 + 7 = 9 10 | 所以返回 [0, 1] 11 | */ 12 | 13 | /* 14 | O(n2) 15 | */ 16 | func twoSum1(nums []int, target int) []int { 17 | ret := make([]int, 0) 18 | if len(nums) < 2 { 19 | return ret 20 | } 21 | for i := 0; i < len(nums); i++ { 22 | for j := i + 1; j < len(nums); j++ { 23 | if nums[i]+nums[j] == target { 24 | ret = append(ret, i) 25 | ret = append(ret, j) 26 | } 27 | } 28 | } 29 | return ret 30 | } 31 | 32 | /* 33 | O(n) 34 | */ 35 | func twoSum2(nums []int, target int) []int { 36 | ret := make([]int, 0) 37 | mp := make(map[int]int) 38 | if len(nums) < 2 { 39 | return ret 40 | } 41 | for i := 0; i < len(nums); i++ { 42 | if v, ok := mp[target-nums[i]]; ok { 43 | ret = append(ret, i, v) 44 | } else { 45 | mp[nums[i]] = i 46 | } 47 | } 48 | return ret 49 | } 50 | -------------------------------------------------------------------------------- /problem/101.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个二叉树,检查它是否是镜像对称的。 5 | 6 | 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 7 | 8 | 1 9 | / \ 10 | 2 2 11 | / \ / \ 12 | 3 4 4 3 13 | 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 14 | 15 | 1 16 | / \ 17 | 2 2 18 | \ \ 19 | 3 3 20 | */ 21 | 22 | type TreeNode struct { 23 | Val int 24 | Left *TreeNode 25 | Right *TreeNode 26 | } 27 | 28 | func isMirror(r1, r2 *TreeNode) bool { 29 | if r1 == nil && r2 == nil { 30 | return true 31 | } 32 | if r1 == nil || r2 == nil { 33 | return false 34 | } 35 | if r1.Val != r2.Val { 36 | return false 37 | } 38 | return isMirror(r1.Left, r2.Right) && isMirror(r1.Right, r2.Left) 39 | } 40 | 41 | func isSymmetric(root *TreeNode) bool { 42 | return isMirror(root, root) 43 | } 44 | -------------------------------------------------------------------------------- /problem/111.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | func minDepth(root *TreeNode) int { 4 | if root == nil { 5 | return 0 6 | } 7 | 8 | if root.Left == nil && root.Right == nil { 9 | return 1 10 | } 11 | 12 | if root.Left == nil { 13 | return minDepth(root.Right) + 1 14 | } 15 | 16 | if root.Right == nil { 17 | return minDepth(root.Left) + 1 18 | } 19 | 20 | return min(minDepth(root.Left), minDepth(root.Right)) + 1 21 | } 22 | 23 | func min(a, b int) int { 24 | if a > b { 25 | return b 26 | } 27 | return a 28 | } 29 | -------------------------------------------------------------------------------- /problem/114.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个二叉树,原地将它展开为链表。 5 | 6 | 例如,给定二叉树 7 | 8 | 1 9 | / \ 10 | 2 5 11 | / \ \ 12 | 3 4 6 13 | 将其展开为: 14 | 15 | 1 16 | \ 17 | 2 18 | \ 19 | 3 20 | \ 21 | 4 22 | \ 23 | 5 24 | \ 25 | 6 26 | */ 27 | 28 | func flatten(root *TreeNode) { 29 | if root == nil { 30 | return 31 | } 32 | cur := root 33 | cur1 := cur 34 | for cur1 != nil { 35 | cur = cur1 36 | if cur.Left != nil { 37 | cur = cur.Left 38 | for cur.Right != nil { 39 | cur = cur.Right 40 | } 41 | cur.Right = cur1.Right 42 | tmp := cur1.Left 43 | cur1.Left = nil 44 | cur1.Right = tmp 45 | } 46 | cur1 = cur1.Right 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /problem/130.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 5 | 给定一个二维的矩阵,包含 'X' 和 'O'(字母 O)。 6 | 7 | 找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。 8 | 9 | 示例: 10 | 11 | X X X X 12 | X O O X 13 | X X O X 14 | X O X X 15 | 运行你的函数后,矩阵变为: 16 | 17 | X X X X 18 | X X X X 19 | X X X X 20 | X O X X 21 | 22 | 来源:力扣(LeetCode) 23 | 链接:https://leetcode-cn.com/problems/surrounded-regions 24 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 25 | 26 | */ 27 | 28 | func solve(board [][]byte) { 29 | for i := 0; i < len(board); i ++ { 30 | for j := 0; j < len(board[i]); j ++ { 31 | if i != 0 && j != 0 && i != len(board) - 1 && j != len(board[i]) - 1 { 32 | continue 33 | } 34 | if board[i][j] == 'O' { 35 | mark(board, i, j) 36 | } 37 | } 38 | } 39 | for i := 0; i < len(board); i ++ { 40 | for j := 0; j < len(board[i]); j ++ { 41 | if board[i][j] == 'O' { 42 | board[i][j] = 'X' 43 | } else if board[i][j] == 'M' { 44 | board[i][j] = 'O' 45 | } 46 | } 47 | } 48 | 49 | //for i := 0; i < len(board); i ++ { 50 | // for j := 0; j < len(board[i]); j ++ { 51 | // fmt.Print(string(board[i][j])) 52 | // } 53 | // fmt.Println() 54 | //} 55 | 56 | } 57 | 58 | func mark(board [][]byte, i int, j int) { 59 | board[i][j] = 'M'//标记 60 | 61 | //向左 62 | if j - 1 >= 0 && board[i][j - 1] == 'O' { 63 | mark(board, i, j - 1) 64 | } 65 | 66 | //向右 67 | if j + 1 < len(board[i]) && board[i][j + 1] == 'O' { 68 | mark(board, i, j + 1) 69 | } 70 | 71 | //向前 72 | if i - 1 >= 0 && board[i - 1][j] == 'O' { 73 | mark(board, i - 1, j) 74 | } 75 | 76 | //向后 77 | if i + 1 < len(board) && board[i + 1][j] == 'O' { 78 | mark(board, i + 1, j) 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /problem/141.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个链表,判断链表中是否有环。 5 | 6 | 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 7 | 8 | 9 | 10 | 示例 1: 11 | 12 | 输入:head = [3,2,0,-4], pos = 1 13 | 输出:true 14 | 解释:链表中有一个环,其尾部连接到第二个节点。 15 | 16 | 示例 2: 17 | 18 | 输入:head = [1,2], pos = 0 19 | 输出:true 20 | 解释:链表中有一个环,其尾部连接到第一个节点。 21 | 22 | 示例 3: 23 | 24 | 输入:head = [1], pos = -1 25 | 输出:false 26 | 解释:链表中没有环。 27 | */ 28 | 29 | func hasCycle(head *ListNode) bool { 30 | k := head 31 | m := head 32 | for k != nil && m != nil { 33 | k = k.Next 34 | if k == nil { 35 | return false 36 | } 37 | k = k.Next 38 | m = m.Next 39 | if k == m { 40 | return true 41 | } 42 | } 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /problem/142.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /** 4 | 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 5 | 6 | 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 7 | 8 | 说明:不允许修改给定的链表。 9 | 10 |   11 | 12 | 示例 1: 13 | 14 | 输入:head = [3,2,0,-4], pos = 1 15 | 输出:tail connects to node index 1 16 | 解释:链表中有一个环,其尾部连接到第二个节点。 17 | 18 | 19 | 示例 2: 20 | 21 | 输入:head = [1,2], pos = 0 22 | 输出:tail connects to node index 0 23 | 解释:链表中有一个环,其尾部连接到第一个节点。 24 | 25 | 26 | 示例 3: 27 | 28 | 输入:head = [1], pos = -1 29 | 输出:no cycle 30 | 解释:链表中没有环。 31 | 32 | * Definition for singly-linked list. 33 | * type ListNode struct { 34 | * Val int 35 | * Next *ListNode 36 | * } 37 | */ 38 | func detectCycle(head *ListNode) *ListNode { 39 | // 判断是否有环 40 | if head == nil || head.Next == nil { //没有直接返回 41 | return nil 42 | } 43 | fast := head 44 | slow := head 45 | if fast == nil || slow == nil { 46 | return nil 47 | } 48 | // 循环连表判断是否有环 49 | for fast != nil && slow != nil && fast.Next != nil { 50 | fast = fast.Next.Next 51 | slow = slow.Next 52 | if fast == slow { 53 | // 环相遇 54 | slow = head 55 | for slow != fast { 56 | slow = slow.Next 57 | fast = fast.Next 58 | } 59 | return slow 60 | } 61 | } 62 | return nil 63 | } -------------------------------------------------------------------------------- /problem/147.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 对链表进行插入排序。 5 | 6 | 7 | 插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。 8 | 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。 9 | 10 | 11 | 12 | 插入排序算法: 13 | 14 | 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。 15 | 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。 16 | 重复直到所有输入数据插入完为止。 17 | 18 | 19 | 示例 1: 20 | 21 | 输入: 4->2->1->3 22 | 输出: 1->2->3->4 23 | 示例 2: 24 | 25 | 输入: -1->5->3->4->0 26 | 输出: -1->0->3->4->5 27 | */ 28 | 29 | func insertionSortList(head *ListNode) *ListNode { 30 | if head == nil || head.Next == nil { 31 | return head 32 | } 33 | originNode := &ListNode{Next: head} 34 | //指向当前位置的指针 35 | preCur := head 36 | cur := head.Next 37 | for cur != nil { 38 | sortNode := originNode 39 | for sortNode.Next != cur { 40 | if cur.Val < sortNode.Next.Val { 41 | preCur.Next = cur.Next 42 | cur.Next = sortNode.Next 43 | sortNode.Next = cur 44 | // 如果有节点插入 45 | cur = preCur.Next 46 | break 47 | } 48 | sortNode = sortNode.Next 49 | } 50 | if sortNode.Next == cur { 51 | // 如果没有节点插入 52 | preCur = preCur.Next 53 | cur = cur.Next 54 | } 55 | } 56 | return originNode.Next 57 | } 58 | -------------------------------------------------------------------------------- /problem/160.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 编写一个程序,找到两个单链表相交的起始节点。 5 | 6 | 如下面的两个链表: 7 | 在节点 c1 开始相交。 8 | 9 | 示例 1: 10 | 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 11 | 输出:Reference of the node with value = 8 12 | 输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。 13 | 14 | 示例 2: 15 | 输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 16 | 输出:Reference of the node with value = 2 17 | 输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。 18 | 19 | 示例 3: 20 | 输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 21 | 输出:null 22 | 输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。 23 | 解释:这两个链表不相交,因此返回 null。 24 | */ 25 | 26 | func getIntersectionNode(headA, headB *ListNode) *ListNode { 27 | if headA == nil { 28 | return nil 29 | } 30 | if headB == nil { 31 | return nil 32 | } 33 | h1, h2 := headA, headB 34 | has1, has2 := false, false 35 | for h1 != nil || h2 != nil { 36 | if h1 == h2 { 37 | return h1 38 | } 39 | h1 = h1.Next 40 | h2 = h2.Next 41 | if h1 == nil && has1 == false { 42 | h1 = headB 43 | has1 = true 44 | } 45 | if h2 == nil && has2 == false { 46 | h2 = headA 47 | has2 = true 48 | } 49 | } 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /problem/179.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。 5 | 6 | 示例 1: 7 | 8 | 输入: [10,2] 9 | 输出: 210 10 | 示例 2: 11 | 12 | 输入: [3,30,34,5,9] 13 | 输出: 9534330 14 | 说明: 输出结果可能非常大,所以你需要返回一个字符串而不是整数。 15 | */ 16 | 17 | func largestNumber(nums []int) string { 18 | 19 | arrLen := len(nums) //空数组的情况下 20 | if arrLen == 0 { 21 | return "0" 22 | } 23 | 24 | sum := 0 //数组参数都是0的情况下 25 | for _, num := range nums { 26 | sum += num 27 | } 28 | if sum == 0 { 29 | return "0" 30 | } 31 | 32 | length := len(nums) 33 | for i := 0; i < length; i++ { 34 | 35 | for j := 0; j < length-i-1; j++ { 36 | 37 | s1 := strconv.Itoa(nums[j]) + strconv.Itoa(nums[j+1]) 38 | s2 := strconv.Itoa(nums[j+1]) + strconv.Itoa(nums[j]) 39 | s1Int, _ := strconv.Atoi(s1) 40 | s2Int, _ := strconv.Atoi(s2) 41 | 42 | if s1Int < s2Int { 43 | nums[j], nums[j+1] = nums[j+1], nums[j] 44 | } 45 | } 46 | } 47 | s := make([]string, length) 48 | for i := range nums { 49 | s[i] = strconv.Itoa(nums[i]) 50 | } 51 | return strings.Join(s, "") 52 | 53 | } 54 | -------------------------------------------------------------------------------- /problem/19.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 5 | 6 | 示例: 7 | 8 | 给定一个链表: 1->2->3->4->5, 和 n = 2. 9 | 10 | 当删除了倒数第二个节点后,链表变为 1->2->3->5. 11 | */ 12 | 13 | type ListNode struct { 14 | Val int 15 | Next *ListNode 16 | } 17 | 18 | func removeNthFromEnd(head *ListNode, n int) *ListNode { 19 | if n <= 0 || head == nil { 20 | return head 21 | } 22 | fast := head 23 | for i := 1; i <= n && fast != nil; i++ { 24 | fast = fast.Next 25 | } 26 | 27 | if fast == nil { 28 | return head.Next 29 | } 30 | 31 | slow := head 32 | for fast.Next != nil { 33 | slow = slow.Next 34 | fast = fast.Next 35 | } 36 | slow.Next = slow.Next.Next 37 | return head 38 | } 39 | -------------------------------------------------------------------------------- /problem/2.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 5 | 6 | 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 7 | 8 | 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 9 | 10 | 示例: 11 | 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 12 | 输出:7 -> 0 -> 8 13 | 原因:342 + 465 = 807 14 | */ 15 | 16 | func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { 17 | ret := &ListNode{0, nil} 18 | tmp := ret 19 | jw, sum := 0, 0 20 | for (l1 != nil && l2 != nil) || jw != 0 { 21 | val1, val2 := 0, 0 22 | if l1 != nil { 23 | val1 = l1.Val 24 | l1 = l1.Next 25 | } 26 | if l2 != nil { 27 | val2 = l2.Val 28 | l2 = l2.Next 29 | } 30 | sum = val1 + val2 + jw 31 | jw = sum / 10 32 | tmp.Next = &ListNode{sum % 10, nil} 33 | tmp = tmp.Next 34 | } 35 | if l1 != nil { 36 | tmp.Next = l1 37 | } 38 | if l2 != nil { 39 | tmp.Next = l2 40 | } 41 | return ret.Next 42 | } 43 | -------------------------------------------------------------------------------- /problem/203.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 删除链表中等于给定值 val 的所有节点。 5 | 6 | 示例: 7 | 8 | 输入: 1->2->6->3->4->5->6, val = 6 9 | 输出: 1->2->3->4->5 10 | */ 11 | 12 | func removeElements(head *ListNode, val int) *ListNode { 13 | if head == nil { 14 | return head 15 | } 16 | if head == nil { 17 | return head 18 | } 19 | h := &ListNode{0, head} 20 | ret := h 21 | for h.Next != nil { 22 | if h.Next.Val == val { 23 | h.Next = h.Next.Next 24 | } else { 25 | h = h.Next 26 | } 27 | } 28 | return ret.Next 29 | } 30 | -------------------------------------------------------------------------------- /problem/213.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import "math" 4 | 5 | /* 6 | 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。 7 | 这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。 8 | 同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 9 | 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。 10 | 11 | 示例 1: 12 | 13 | 输入: [2,3,2] 14 | 输出: 3 15 | 解释: 你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。 16 | 17 | 解题思路: 18 | 由于他是一个闭环,所以可以把问题分解成n[1]~n[n-1] 和 n[2]~n[n] 中取最大值的子问题 19 | 然后分别n[1]~n[n-1]又可以看成线性的打家劫舍1问题 20 | */ 21 | 22 | func rob(nums []int) int { 23 | handler := func(sub []int) int { 24 | if len(sub) == 0 { 25 | return 0 26 | } 27 | if len(sub) == 1 { 28 | return sub[0] 29 | } 30 | if len(sub) == 2 { 31 | return int(math.Max(float64(sub[0]), float64(sub[1]))) 32 | } 33 | dp := make([]int, len(sub)) 34 | dp[0] = sub[0] 35 | dp[1] = int(math.Max(float64(sub[0]), float64(sub[1]))) 36 | for i := 2; i < len(sub); i++ { 37 | dp[i] = int(math.Max(float64(dp[i-2]+sub[i]), float64(dp[i-1]))) 38 | } 39 | return dp[len(dp)-1] 40 | } 41 | if len(nums) == 1 { 42 | return nums[0] 43 | } 44 | sub1 := make([]int, 0) 45 | sub2 := make([]int, 0) 46 | for idx, cur := range nums { 47 | if idx <= len(nums)-2 { 48 | sub1 = append(sub1, cur) 49 | } 50 | if idx >= 1 && idx <= len(nums)-1 { 51 | sub2 = append(sub2, cur) 52 | } 53 | } 54 | return int(math.Max(float64(handler(sub1)), float64(handler(sub2)))) 55 | } 56 | -------------------------------------------------------------------------------- /problem/226.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 翻转一棵二叉树。 5 | 6 | 示例: 7 | 8 | 输入: 9 | 10 | 4 11 | / \ 12 | 2 7 13 | / \ / \ 14 | 1 3 6 9 15 | 输出: 16 | 17 | 4 18 | / \ 19 | 7 2 20 | / \ / \ 21 | 9 6 3 1 22 | */ 23 | 24 | func invertTree(root *TreeNode) *TreeNode { 25 | if root == nil { 26 | return root 27 | } 28 | root.Right, root.Left = invertTree(root.Left), invertTree(root.Right) 29 | return root 30 | } 31 | -------------------------------------------------------------------------------- /problem/23.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | //合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 4 | //示例: 5 | //输入: 6 | //[ 7 | //  1->4->5, 8 | //  1->3->4, 9 | //  2->6 10 | //] 11 | //输出: 1->1->2->3->4->4->5->6 12 | func mergeKLists(lists []*ListNode) *ListNode { 13 | if len(lists) == 0 { 14 | return nil 15 | } 16 | mNode := &ListNode{Next:lists[0]} 17 | for i:=1;i2 9 | 输出: false 10 | 示例 2: 11 | 12 | 输入: 1->2->2->1 13 | 输出: true 14 | */ 15 | 16 | func isPalindrome(head *ListNode) bool { 17 | if head == nil { 18 | return true 19 | } 20 | ret := make([]int, 0) 21 | h := head 22 | for h != nil { 23 | ret = append(ret, h.Val) 24 | h = h.Next 25 | } 26 | l, r := 0, len(ret)-1 27 | for l < r { 28 | if ret[l] != ret[r] { 29 | return false 30 | } 31 | l++ 32 | r-- 33 | } 34 | return true 35 | } 36 | -------------------------------------------------------------------------------- /problem/236.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 5 | 6 | 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 7 | 8 | 例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4] 9 | 10 | 示例 1: 11 | 12 | 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 13 | 输出: 3 14 | 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 15 | 示例 2: 16 | 17 | 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 18 | 输出: 5 19 | 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。 20 | */ 21 | 22 | func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { 23 | if root == nil || root == p || root == q { 24 | return root 25 | } 26 | left := lowestCommonAncestor(root.Left, p, q) 27 | right := lowestCommonAncestor(root.Right, p, q) 28 | if left != nil && right != nil { 29 | return root 30 | } 31 | if left != nil { 32 | return left 33 | } 34 | if right != nil { 35 | return right 36 | } 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /problem/239.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import "container/list" 4 | 5 | /* 6 | 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。 7 | 返回滑动窗口最大值。 8 | 9 | 示例: 10 | 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 11 | 输出: [3,3,5,5,6,7] 12 | 解释: 13 | 14 | 滑动窗口的位置 最大值 15 | --------------- ----- 16 | [1 3 -1] -3 5 3 6 7 3 17 | 1 [3 -1 -3] 5 3 6 7 3 18 | 1 3 [-1 -3 5] 3 6 7 5 19 | 1 3 -1 [-3 5 3] 6 7 5 20 | 1 3 -1 -3 [5 3 6] 7 6 21 | 1 3 -1 -3 5 [3 6 7] 7 22 | */ 23 | 24 | func maxSlidingWindow(nums []int, k int) []int { 25 | if k <= 1 { 26 | return nums 27 | } 28 | 29 | //list是一个双向链表,存储当前窗口的最大值。 30 | 31 | queue := list.New() 32 | //result 存放所有滑动窗口的最大值 33 | result := make([]int, 0, len(nums)-k+1) 34 | 35 | for i, v := range nums { 36 | for queue.Len() > 0 { 37 | // 如果当前数字大于队列尾,则删除队列尾,直到当前数字小于等于队列尾,或者队列空 38 | if x := queue.Back(); nums[x.Value.(int)] <= v { 39 | queue.Remove(x) 40 | } else { 41 | break 42 | } 43 | } 44 | //当前元素入队列 45 | queue.PushBack(i) 46 | // 如果队列头元素不在滑动窗口中了,就删除头元素 47 | for x, j := queue.Front(), i-k+1; x.Value.(int) < j; x = queue.Front() { 48 | queue.Remove(x) 49 | } 50 | //形成第一个滑动窗口时,才把队首元素放入结果集 51 | if i >= k-1 { 52 | result = append(result, nums[queue.Front().Value.(int)]) 53 | } 54 | } 55 | 56 | return result 57 | } 58 | -------------------------------------------------------------------------------- /problem/26.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 5 | 6 | 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 7 | 8 | 示例 1: 9 | 10 | 给定数组 nums = [1,1,2], 11 | 12 | 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 13 | 14 | 你不需要考虑数组中超出新长度后面的元素。 15 | 示例 2: 16 | 17 | 给定 nums = [0,0,1,1,1,2,2,3,3,4], 18 | 19 | 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 20 | 21 | 你不需要考虑数组中超出新长度后面的元素。 22 | */ 23 | 24 | func removeDuplicates(nums []int) int { 25 | if len(nums) < 2 { 26 | return len(nums) 27 | } 28 | left, right := 0, 1 29 | for ; right < len(nums); right++ { 30 | if nums[left] == nums[right] { 31 | continue 32 | } 33 | left++ 34 | nums[left] = nums[right] 35 | } 36 | nums = nums[:left+1] 37 | return len(nums) 38 | } 39 | -------------------------------------------------------------------------------- /problem/27.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。 5 | 6 | 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 7 | 8 | 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 9 | 10 | 示例 1: 11 | 12 | 给定 nums = [3,2,2,3], val = 3, 13 | 14 | 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 15 | 16 | 你不需要考虑数组中超出新长度后面的元素。 17 | 示例 2: 18 | 19 | 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 20 | 21 | 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。 22 | 23 | 注意这五个元素可为任意顺序。 24 | 25 | 你不需要考虑数组中超出新长度后面的元素。 26 | */ 27 | 28 | func removeElement(nums []int, val int) int { 29 | if len(nums) == 0 { 30 | return 0 31 | } 32 | index := 0 33 | for ; index < len(nums); { 34 | if nums[index] == val { 35 | nums = append(nums[:index], nums[index+1:]...) 36 | continue 37 | } 38 | index++ 39 | } 40 | return len(nums) 41 | } 42 | -------------------------------------------------------------------------------- /problem/295.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import "container/heap" 4 | 5 | /* 6 | 295.数据流的中位数 7 | 中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 8 | 9 | 例如, 10 | 11 | [2,3,4] 的中位数是 3 12 | 13 | [2,3] 的中位数是 (2 + 3) / 2 = 2.5 14 | 15 | 设计一个支持以下两种操作的数据结构: 16 | 17 | void addNum(int num) - 从数据流中添加一个整数到数据结构中。 18 | double findMedian() - 返回目前所有元素的中位数。 19 | 20 | 示例: 21 | 22 | addNum(1) 23 | addNum(2) 24 | findMedian() -> 1.5 25 | addNum(3) 26 | findMedian() -> 2 27 | */ 28 | 29 | type IntPQ []int 30 | 31 | func (pq IntPQ) Len() int { return len(pq) } 32 | 33 | func (pq IntPQ) Less(i int, j int) bool { return pq[i] < pq[j] } 34 | 35 | func (pq IntPQ) Swap(i int, j int) { pq[i], pq[j] = pq[j], pq[i] } 36 | 37 | func (pq *IntPQ) Push(x interface{}) { 38 | *pq = append(*pq, x.(int)) 39 | } 40 | 41 | func (pq *IntPQ) Pop() interface{} { 42 | old := *pq 43 | 44 | x := old[len(old)-1] 45 | *pq = old[:len(old)-1] 46 | 47 | return x 48 | } 49 | 50 | type MedianFinder struct { 51 | lows IntPQ 52 | highs IntPQ 53 | } 54 | 55 | func Constructor() MedianFinder { 56 | return MedianFinder{} 57 | } 58 | 59 | func (this *MedianFinder) AddNum(num int) { 60 | if this.lows.Len() == this.highs.Len() { 61 | heap.Push(&this.highs, num) 62 | } else { 63 | heap.Push(&this.lows, -num) 64 | } 65 | 66 | // re-balance 67 | if this.lows.Len() == 0 { 68 | return 69 | } 70 | 71 | x, y := -this.lows[0], this.highs[0] 72 | if x > y { 73 | heap.Pop(&this.lows) 74 | heap.Pop(&this.highs) 75 | 76 | heap.Push(&this.lows, -y) 77 | heap.Push(&this.highs, x) 78 | } 79 | } 80 | 81 | func (this *MedianFinder) FindMedian() float64 { 82 | if this.highs.Len() > this.lows.Len() { 83 | return float64(this.highs[0]) 84 | } 85 | 86 | return (float64(this.highs[0]) - float64(this.lows[0])) / 2 87 | } 88 | -------------------------------------------------------------------------------- /problem/3.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。 5 | 6 | 示例 1: 7 | 输入: "abcabcbb" 8 | 输出: 3 9 | 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 10 | 11 | 示例 2: 12 | 输入: "bbbbb" 13 | 输出: 1 14 | 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 15 | 16 | 示例 3: 17 | 输入: "pwwkew" 18 | 输出: 3 19 | 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 20 |   请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 21 | */ 22 | 23 | func lengthOfLongestSubstring(s string) int { 24 | n := len(s) 25 | if n < 2 { 26 | return n 27 | } 28 | max := 0 29 | for i := 0; i < n; i++ { 30 | mp := make(map[uint8]int) 31 | mp[s[i]] = 1 32 | for j := i + 1; j < n; j++ { 33 | if _, ok := mp[s[j]]; !ok { 34 | mp[s[j]] = 1 35 | } else { 36 | break 37 | } 38 | } 39 | if max < len(mp) { 40 | max = len(mp) 41 | } 42 | } 43 | return max 44 | } 45 | -------------------------------------------------------------------------------- /problem/310.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /** 4 | 最小高度树 5 | 解题思路:最小高度树的特点是根节点位于某条最长路径的中点,中点可能是一个,也有可能是两个 6 | 通过一层一层地将边缘的叶子节点去掉之后,最后保存下来的一个或者两个点就是结果。叶子节点的特点是只有一条边。 7 | */ 8 | 9 | func findMinHeightTrees(n int, edges [][]int) []int { 10 | if n == 1 { 11 | return []int{0} 12 | } 13 | nodes := make([][]int, n) 14 | for i:=0; i < n; i ++ { 15 | nodes[i] = make([]int, 0, 3) 16 | } 17 | count := make([]int, n) 18 | for _, edge := range edges { 19 | nodes[edge[0]] = append(nodes[edge[0]], edge[1]) 20 | nodes[edge[1]] = append(nodes[edge[1]], edge[0]) 21 | count[edge[0]] ++ 22 | count[edge[1]] ++ 23 | } 24 | leaves := make([]int, 0) 25 | for i := 0; i 2 { 32 | newLeaves := make([]int, 0, len(leaves)) 33 | for _, leaf = range leaves { 34 | n -- 35 | for _, leafNode = range nodes[leaf] { 36 | count[leafNode] -- 37 | if count[leafNode] == 1 { 38 | newLeaves = append(newLeaves, leafNode) 39 | } 40 | } 41 | } 42 | leaves = newLeaves 43 | } 44 | return leaves 45 | } 46 | -------------------------------------------------------------------------------- /problem/322.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。 5 | 6 | 示例 1: 7 | 输入: coins = [1, 2, 5], amount = 11 8 | 输出: 3 9 | 解释: 11 = 5 + 5 + 1 10 | 11 | 示例 2: 12 | 输入: coins = [2], amount = 3 13 | 输出: -1 14 | 说明: 15 | 你可以认为每种硬币的数量是无限的。 16 | */ 17 | 18 | func coinChange(coins []int, amount int) int { 19 | dp := make([]int, amount+1) 20 | for j := 1; j <= amount; j++ { 21 | dp[j] = amount + 1 22 | } 23 | for i := 1; i <= amount; i++ { 24 | for _, v := range coins { 25 | if i >= v { 26 | dp[i] = min(dp[i], dp[i-v]+1) 27 | } 28 | } 29 | } 30 | if dp[amount] > amount { 31 | return -1 32 | } 33 | return dp[amount] 34 | } 35 | 36 | func min(i, j int) int { 37 | if i < j { 38 | return i 39 | } 40 | return j 41 | } 42 | -------------------------------------------------------------------------------- /problem/347.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个非空的整数数组,返回其中出现频率前 k 高的元素。 5 | 6 | 示例 1: 7 | 8 | 输入: nums = [1,1,1,2,2,3], k = 2 9 | 输出: [1,2] 10 | 示例 2: 11 | 12 | 输入: nums = [1], k = 1 13 | 输出: [1] 14 | 说明: 15 | 16 | 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 17 | 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。 18 | */ 19 | 20 | func topKFrequent(nums []int, k int) []int { 21 | ret := make([]int, 0) 22 | if len(nums) == 0 { 23 | return ret 24 | } 25 | maxCount := 0 26 | element2CountMap := make(map[int]int, 0) 27 | for _,num := range nums { 28 | element2CountMap[num]++ 29 | if element2CountMap[num] > maxCount { 30 | maxCount = element2CountMap[num] 31 | } 32 | } 33 | tmp := make([][]int,maxCount+1) 34 | for k,v := range element2CountMap{ 35 | tmp[v] = append(tmp[v], k) 36 | } 37 | for i:=maxCount;i>=0;i--{ 38 | if len(tmp[i]) == 0 { 39 | continue 40 | } 41 | ret = append(ret, tmp[i]...) 42 | if len(ret) == k { 43 | break 44 | } 45 | } 46 | return ret 47 | } -------------------------------------------------------------------------------- /problem/35.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 5 | 6 | 你可以假设数组中无重复元素。 7 | 8 | 示例 1: 9 | 10 | 输入: [1,3,5,6], 5 11 | 输出: 2 12 | 示例 2: 13 | 14 | 输入: [1,3,5,6], 2 15 | 输出: 1 16 | 示例 3: 17 | 18 | 输入: [1,3,5,6], 7 19 | 输出: 4 20 | 示例 4: 21 | 22 | 输入: [1,3,5,6], 0 23 | 输出: 0 24 | */ 25 | 26 | func searchInsert(nums []int, target int) int { 27 | if len(nums) == 0 { 28 | return 0 29 | } 30 | i := 0 31 | for i < len(nums) { 32 | if nums[i] < target { 33 | i++ 34 | } else if nums[i] == target { 35 | return i 36 | } else { 37 | break; 38 | } 39 | } 40 | return i 41 | } 42 | -------------------------------------------------------------------------------- /problem/355.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import ( 4 | "time" 5 | "sort" 6 | ) 7 | 8 | /* 9 | 设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近十条推文。你的设计需要支持以下的几个功能: 10 | 11 | postTweet(userId, tweetId): 创建一条新的推文 12 | getNewsFeed(userId): 检索最近的十条推文。每个推文都必须是由此用户关注的人或者是用户自己发出的。推文必须按照时间顺序由最近的开始排序。 13 | follow(followerId, followeeId): 关注一个用户 14 | unfollow(followerId, followeeId): 取消关注一个用户 15 | 示例: 16 | Twitter twitter = new Twitter(); 17 | 18 | // 用户1发送了一条新推文 (用户id = 1, 推文id = 5). 19 | twitter.postTweet(1, 5); 20 | 21 | // 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文. 22 | twitter.getNewsFeed(1); 23 | 24 | // 用户1关注了用户2. 25 | twitter.follow(1, 2); 26 | 27 | // 用户2发送了一个新推文 (推文id = 6). 28 | twitter.postTweet(2, 6); 29 | 30 | // 用户1的获取推文应当返回一个列表,其中包含两个推文,id分别为 -> [6, 5]. 31 | // 推文id6应当在推文id5之前,因为它是在5之后发送的. 32 | twitter.getNewsFeed(1); 33 | 34 | // 用户1取消关注了用户2. 35 | twitter.unfollow(1, 2); 36 | 37 | // 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文. 38 | // 因为用户1已经不再关注用户2. 39 | twitter.getNewsFeed(1); 40 | */ 41 | 42 | type Twit struct { 43 | TwitId int 44 | Time time.Time 45 | } 46 | 47 | type Twits []Twit 48 | 49 | func (t Twits) Len() int { 50 | return len(t) 51 | } 52 | 53 | func (t Twits) Less(i, j int) bool { 54 | if t[i].Time.After(t[j].Time) { 55 | return true 56 | } 57 | return false 58 | } 59 | 60 | func (t Twits) Swap(i, j int) { 61 | t[i], t[j] = t[j], t[i] 62 | } 63 | 64 | type Twitter struct { 65 | UserTwit map[int]Twits 66 | UserFollow map[int][]int 67 | } 68 | 69 | /** Initialize your data structure here. */ 70 | func Constructor() Twitter { 71 | return Twitter{ 72 | UserTwit: make(map[int]Twits), 73 | UserFollow: make(map[int][]int), 74 | } 75 | } 76 | 77 | /** Compose a new tweet. */ 78 | func (this *Twitter) PostTweet(userId int, tweetId int) { 79 | this.UserTwit[userId] = append(this.UserTwit[userId], Twit{ 80 | tweetId, 81 | time.Now(), 82 | }) 83 | } 84 | 85 | /** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */ 86 | func (this *Twitter) GetNewsFeed(userId int) []int { 87 | ret := make([]int, 0) 88 | temp := make(Twits, this.UserTwit[userId].Len()) 89 | copy(temp, this.UserTwit[userId]) 90 | for _, v := range this.UserFollow[userId] { 91 | temp = append(temp, this.UserTwit[v]...) 92 | } 93 | sort.Sort(temp) 94 | for i := 0; i < 10 && i < temp.Len(); i++ { 95 | ret = append(ret, temp[i].TwitId) 96 | } 97 | return ret 98 | } 99 | 100 | /** Follower follows a followee. If the operation is invalid, it should be a no-op. */ 101 | func (this *Twitter) Follow(followerId int, followeeId int) { 102 | if followerId == followeeId { 103 | return 104 | } 105 | for _, v := range this.UserFollow[followerId] { 106 | if v == followeeId { 107 | return 108 | } 109 | } 110 | this.UserFollow[followerId] = append(this.UserFollow[followerId], followeeId) 111 | } 112 | 113 | /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */ 114 | func (this *Twitter) Unfollow(followerId int, followeeId int) { 115 | if followerId == followeeId { 116 | return 117 | } 118 | for i, v := range this.UserFollow[followerId] { 119 | if v == followeeId { 120 | this.UserFollow[followerId] = append(this.UserFollow[followerId][:i], this.UserFollow[followerId][i+1:]...) 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /problem/373.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | /* 9 | 10 | 给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。 11 | 12 | 定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2。 13 | 14 | 找到和最小的 k 对数字 (u1,v1), (u2,v2) ... (uk,vk)。 15 | 16 | 示例 1: 17 | 18 | 输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3 19 | 输出: [1,2],[1,4],[1,6] 20 | 解释: 返回序列中的前 3 对数: 21 | [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6] 22 | 示例 2: 23 | 24 | 输入: nums1 = [1,1,2], nums2 = [1,2,3], k = 2 25 | 输出: [1,1],[1,1] 26 | 解释: 返回序列中的前 2 对数: 27 |   [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3] 28 | 示例 3: 29 | 30 | 输入: nums1 = [1,2], nums2 = [3], k = 3 31 | 输出: [1,3],[2,3] 32 | 解释: 也可能序列中所有的数对都被返回:[1,3],[2,3] 33 | 34 | 35 | */ 36 | 37 | /* 38 | 解题: 39 | 解法法一 :kSmallestPairs 40 | 最先想到用最直接的方式解决,把所有的情况放到二位数据里 41 | 然后对二维数组按照 和排序 42 | 然后取出 k对或者 len(nums1) * len(nums2)对数组 43 | 44 | 最后用了 插入排序 超时不通过 45 | 46 | 然后用了 map[int][][]int{} 这个结构 map 的key 存储 u+v 的值 47 | 48 | 将key 的值 放进 []int 然后排序 49 | 50 | 循环依次拿出 map 里的值 这个通过了 51 | 52 | 解法二:kSmallestPairsFast 53 | 54 | 解法二用的是堆排序做的,时间复杂度 nlogn 速度很快 55 | 56 | 大顶堆的特点 57 | 58 | root节点为当前堆中最大的值 59 | 是二叉树,并不是平衡二叉树 60 | 父节点一定比子节点大 61 | 62 | 当前节点为index 63 | parent节点 为 (index - 1)/2 64 | leftChild 为 index*2 + 1 65 | rightChjld 为 index*2 + 2 66 | 67 | 每次添加或删除节点 68 | 69 | 重置节点 保证 root 节点为最大值 70 | 71 | 72 | */ 73 | 74 | /* 75 | func main() { 76 | nums1 := []int{1, 7, 11} 77 | nums2 := []int{2, 4, 6} 78 | 79 | nums1 = []int{-476570184, -423568801, -385585840, -375390924, -364630569, -359795128, -281872968, -126410430, -75677925, -54214495, -49178055, -32637211, -32198215, 3413177, 19045759, 62248526, 67551536, 113606647, 155411580, 164755463, 164781059, 203133270, 277305105, 284913246, 285973110, 296436629, 325431544, 357294459, 378678394, 399786157} 80 | nums2 = []int{-408663357, -404578641, -376531700, -311642519, -294905976, -232001207, -183530032, -141524508, -115652480, -70696522, -63386299, -54656543, -32316999, 29714175, 33993996, 45020708, 62165363, 84210823, 93905151, 102177224, 209285622, 288668099, 328300713, 338684779, 342861859, 384940859, 408019604, 410097843, 458721542, 475395296} 81 | //1000 82 | 83 | nums1 = []int{1, 1, 2} 84 | nums2 = []int{1, 2, 3} 85 | 86 | 87 | //[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6] 88 | 89 | a := kSmallestPairsFast(nums1, nums2, 1000) 90 | 91 | fmt.Println(a) 92 | 93 | } 94 | */ 95 | 96 | /* 97 | 方法一 98 | */ 99 | func kSmallestPairs(nums1 []int, nums2 []int, k int) [][]int { 100 | var arr [][]int 101 | var ar []int 102 | if k <= 0 { 103 | return arr 104 | } 105 | lens1 := len(nums1) 106 | lens2 := len(nums2) 107 | if lens1 == 0 || lens2 == 0 { 108 | return arr 109 | } 110 | if k > lens1*lens2 { 111 | k = lens1 * lens2 112 | } 113 | a := map[int][][]int{} 114 | 115 | for _, v := range nums1 { 116 | for _, val := range nums2 { 117 | ar = append(ar, v+val) 118 | a[v+val] = append(a[v+val], []int{v, val}) 119 | } 120 | } 121 | sort.Ints(ar) 122 | 123 | ar = ar[0:k] 124 | for _, v := range ar { 125 | 126 | val := a[v][0] 127 | 128 | arr = append(arr, val) 129 | 130 | a[v] = a[v][1:] 131 | fmt.Println(a[v]) 132 | } 133 | return arr 134 | } 135 | 136 | /* 137 | 方法二 138 | */ 139 | func kSmallestPairsFast(nums1 []int, nums2 []int, k int) [][]int { 140 | n := len(nums1) 141 | m := len(nums2) 142 | if m == 0 || n == 0 || k == 0 { 143 | return nil 144 | } 145 | heap := MaxHeap{ 146 | arr: make([]*Node, k), 147 | } 148 | 149 | for i := 0; i < n; i++ { 150 | for j := 0; j < m; j++ { 151 | if heap.size < k { 152 | heap.Add(&Node{ 153 | a: i, 154 | b: j, 155 | Val: nums1[i] + nums2[j], 156 | }) 157 | } else { 158 | if heap.Top().Val > nums1[i]+nums2[j] { 159 | heap.Pop() 160 | heap.Add(&Node{ 161 | a: i, 162 | b: j, 163 | Val: nums1[i] + nums2[j], 164 | }) 165 | } else { 166 | break 167 | } 168 | } 169 | } 170 | } 171 | ret := make([][]int, heap.Size()) 172 | i := heap.Size() - 1 173 | for !heap.IsEmpty() { 174 | node := heap.Pop() 175 | ret[i] = []int{nums1[node.a], nums2[node.b]} 176 | i-- 177 | } 178 | return ret 179 | } 180 | 181 | /* 182 | 节点结构体 存储 u,v u+v 183 | */ 184 | type Node struct { 185 | a int // nums1[n] 186 | b int // nums2[n] 187 | Val int // nums1[n] + nums2[n] 188 | } 189 | 190 | /* 191 | 大顶堆结构体 MaxHeap[0] 为当前堆中最大值 192 | */ 193 | 194 | type MaxHeap struct { 195 | arr []*Node 196 | size int // 最大为k 或者 为 len(nums1) * len(nums2 197 | } 198 | 199 | /* 200 | 为大顶堆添加 节点 并调整堆的 root 节点为最大值 201 | */ 202 | 203 | func (h *MaxHeap) Add(n *Node) { 204 | h.arr[h.size] = n 205 | pos := h.size 206 | h.size++ 207 | for pos > 0 { 208 | parent := h.Parent(pos) 209 | if h.arr[parent].Val > n.Val { 210 | break 211 | } 212 | h.Swap(parent, pos) 213 | pos = parent 214 | } 215 | } 216 | 217 | /* 218 | 踢出堆的最大值 219 | */ 220 | func (h *MaxHeap) Pop() *Node { 221 | if h.IsEmpty() { 222 | return nil 223 | } 224 | 225 | ret := h.arr[0] 226 | h.size-- 227 | h.arr[0] = h.arr[h.size] 228 | pos := 0 229 | /* 230 | 踢出 堆中最大的值之后 从root节点开始 依次比对左右子节点 231 | 子节点中最大的值 大于 父节点 与父节点调换 232 | 重置堆保证root节点为堆中最大值 233 | */ 234 | for pos < h.size { 235 | left, right := h.Child(pos) 236 | if (left != -1 && h.arr[left].Val > h.arr[pos].Val) || (right != -1 && h.arr[right].Val > h.arr[pos].Val) { 237 | if right != -1 && h.arr[left].Val < h.arr[right].Val { 238 | h.Swap(right, pos) 239 | pos = right 240 | } else { 241 | h.Swap(left, pos) 242 | pos = left 243 | } 244 | } else { 245 | break 246 | } 247 | } 248 | return ret 249 | } 250 | 251 | func (h *MaxHeap) Swap(a, b int) { 252 | tmp := h.arr[a] 253 | h.arr[a] = h.arr[b] 254 | h.arr[b] = tmp 255 | } 256 | 257 | func (h *MaxHeap) IsEmpty() bool { 258 | return h.size == 0 259 | } 260 | 261 | func (h *MaxHeap) Size() int { 262 | return h.size 263 | } 264 | 265 | func (h *MaxHeap) Top() *Node { 266 | if h.IsEmpty() { 267 | return nil 268 | } 269 | return h.arr[0] 270 | } 271 | 272 | func (h *MaxHeap) Parent(pos int) int { 273 | return (pos - 1) / 2 274 | } 275 | 276 | func (h *MaxHeap) Child(pos int) (int, int) { 277 | left := pos*2 + 1 278 | right := pos*2 + 2 279 | if left >= h.size { 280 | left = -1 281 | } 282 | if right >= h.size { 283 | right = -1 284 | } 285 | return left, right 286 | } 287 | -------------------------------------------------------------------------------- /problem/392.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | //给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 4 | // 5 | //你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。 6 | // 7 | //字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。 8 | // 9 | //来源:力扣(LeetCode) 10 | //链接:https://leetcode-cn.com/problems/is-subsequence 11 | //著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 12 | func isSubsequence(s string, t string) bool { 13 | if s == ""{ 14 | return true 15 | } 16 | ls := len(s) 17 | lt := len(t) 18 | var flag = false 19 | tmp := 0 20 | for i := 0; i < ls; i++ { 21 | for j := tmp; j < lt; j++ { 22 | if s[i] == t[j] { 23 | flag = true 24 | tmp = j + 1 25 | break 26 | } 27 | } 28 | if !flag || i+1 == ls { 29 | return flag 30 | } else { 31 | flag = false 32 | } 33 | } 34 | return flag 35 | } 36 | -------------------------------------------------------------------------------- /problem/4.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 5 | 6 | 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 7 | 8 | 你可以假设 nums1 和 nums2 不会同时为空。 9 | 10 | 示例 1: 11 | 12 | nums1 = [1, 3] 13 | nums2 = [2] 14 | 15 | 则中位数是 2.0 16 | 示例 2: 17 | 18 | nums1 = [1, 2] 19 | nums2 = [3, 4] 20 | 21 | 则中位数是 (2 + 3)/2 = 2.5 22 | */ 23 | 24 | func hmax(x, y int) int { 25 | if x > y { 26 | return x 27 | } 28 | return y 29 | } 30 | 31 | func hmin(x, y int) int { 32 | if x > y { 33 | return y 34 | } 35 | return x 36 | } 37 | 38 | func maxArea(height []int) int { 39 | l := 0 40 | r := len(height) - 1 41 | max := 0 42 | for l < r { 43 | max = hmax(max, hmin(height[r], height[l])*(r-l)) 44 | if height[l] < height[r] { 45 | l++ 46 | } else { 47 | r-- 48 | } 49 | } 50 | return max 51 | } 52 | -------------------------------------------------------------------------------- /problem/424.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import "math" 4 | 5 | /* 6 | 题目描述: 7 | 给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。 8 | 9 | 注意: 10 | 字符串长度 和 k 不会超过 104。 11 | 12 | 示例 1: 13 | 输入: 14 | s = "ABAB", k = 2 15 | 16 | 输出: 17 | 4 18 | 19 | 解释: 20 | 用两个'A'替换为两个'B',反之亦然。 21 | */ 22 | 23 | // 思路如下: 24 | // 这里采用滑动窗口,当滑动窗口达到一个最大值后,窗口一直前进 25 | // 当窗口内记载的出现次数最大字符大于上一次的出现最大次数字符时,窗口长度增加 26 | // 否则,窗口保持原来长度前进一个单位 27 | 28 | func characterReplacement(s string, k int) int { 29 | maxCount := 0 30 | l := 0 31 | var r int 32 | count := make([]int, 26) 33 | for r = 0; r < len(s); r++ { 34 | count[s[r]-'A']++ 35 | maxCount = int(math.Max(float64(maxCount), float64(count[s[r]-'A']))) 36 | if r-l+1-maxCount > k { 37 | count[s[l]-'A']-- 38 | l++ 39 | } 40 | } 41 | return r - l 42 | } 43 | -------------------------------------------------------------------------------- /problem/43.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /** 4 | 解题思路 5 | 1. m位和n位数相乘,结果位数为m+n-1或m+n,所以创建一个m+n位数组 6 | 2. 对应位相乘后的结果与进位数据数组对应位置相加,十位数存入进位数组下一位,个位数留在该位 (对10取余数结果为该位数据,进位除以10) 7 | 3. 第一位为0的情况,在转为字符串时记得去掉 8 | */ 9 | 10 | func multiply(num1 string, num2 string) string { 11 | if num1 == "0" || num2 == "0" { 12 | return "0" 13 | } 14 | m, n := len(num1), len(num2) 15 | result := make([]int, m+n) 16 | for j := n - 1; j >= 0; j-- { 17 | for i := m - 1; i >= 0; i-- { 18 | tmp := int(num1[i]-'0')*int(num2[j]-'0') + result[i+j+1] 19 | result[i+j+1] = tmp % 10 20 | result[i+j] += tmp / 10 21 | } 22 | } 23 | if result[0] == 0 { 24 | result = result[1:] 25 | } 26 | length := len(result) 27 | str := make([]byte, length) 28 | for k, val := range result { 29 | str[k] += byte(val) + '0' 30 | } 31 | return string(str) 32 | } 33 | -------------------------------------------------------------------------------- /problem/472.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | type node struct { 4 | child [26]*node 5 | empty bool 6 | } 7 | 8 | func NewNode() *node { 9 | return &node{ 10 | child: [26]*node{}, 11 | empty: true, 12 | } 13 | } 14 | 15 | func findAllConcatenatedWordsInADict(words []string) []string { 16 | root := NewNode() 17 | for _, word := range words { 18 | curr := root 19 | for _, v := range word { 20 | index := v - 97 21 | if curr.child[index] == nil { 22 | curr.child[index] = NewNode() 23 | } 24 | curr = curr.child[index] 25 | } 26 | curr.empty = false 27 | } 28 | var res []string 29 | for _, word := range words { 30 | if Contains(word, root, 0) { 31 | res = append(res, word) 32 | } 33 | } 34 | 35 | return res 36 | } 37 | 38 | func Contains(word string, root *node, count int) bool { 39 | curr := root 40 | for k, v := range word { 41 | curr = curr.child[v-97] 42 | if curr == nil { 43 | return false 44 | } 45 | if !curr.empty { 46 | if k >= len(word)-1 { 47 | return count > 0 48 | } 49 | // cat at a 50 | ww := word[k+1:] 51 | if Contains(string(ww), root, count+1) { 52 | return true 53 | } 54 | } 55 | } 56 | return false 57 | } 58 | 59 | -------------------------------------------------------------------------------- /problem/48.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个 n × n 的二维矩阵表示一个图像。 5 | 6 | 将图像顺时针旋转 90 度。 7 | 8 | 说明: 9 | 10 | 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。 11 | 12 | 示例 1: 13 | 14 | 给定 matrix = 15 | [ 16 | [1,2,3], 17 | [4,5,6], 18 | [7,8,9] 19 | ], 20 | 21 | 原地旋转输入矩阵,使其变为: 22 | [ 23 | [7,4,1], 24 | [8,5,2], 25 | [9,6,3] 26 | ] 27 | 示例 2: 28 | 29 | 给定 matrix = 30 | [ 31 | [ 5, 1, 9,11], 32 | [ 2, 4, 8,10], 33 | [13, 3, 6, 7], 34 | [15,14,12,16] 35 | ], 36 | 37 | 原地旋转输入矩阵,使其变为: 38 | [ 39 | [15,13, 2, 5], 40 | [14, 3, 4, 1], 41 | [12, 6, 8, 9], 42 | [16, 7,10,11] 43 | ] 44 | */ 45 | 46 | func rotate(matrix [][]int) { 47 | n := len(matrix) 48 | for i := 0; i < n/2; i++ { 49 | for j := i; j < n-i-1; j++ { 50 | tmp := matrix[i][j] 51 | matrix[i][j] = matrix[n-j-1][i] 52 | matrix[n-j-1][i] = matrix[n-i-1][n-j-1] 53 | matrix[n-i-1][n-j-1] = matrix[j][n-i-1] 54 | matrix[j][n-i-1] = tmp 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /problem/5.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 5 | 6 | 示例 1: 7 | 输入: "babad" 8 | 输出: "bab" 9 | 注意: "aba" 也是一个有效答案。 10 | 11 | 示例 2: 12 | 输入: "cbbd" 13 | 输出: "bb" 14 | */ 15 | 16 | func ishw(i, j int, s string) bool { 17 | for i <= j { 18 | if s[i] != s[j] { 19 | return false 20 | } 21 | i++ 22 | j-- 23 | } 24 | return true 25 | } 26 | 27 | func longestPalindrome(s string) string { 28 | max := 0 29 | if len(s) < 2 { 30 | return s 31 | } 32 | ret := s[0:1] 33 | for i := 0; i < len(s); i++ { 34 | for j := i + 1; j < len(s); j++ { 35 | if ishw(i, j, s) { 36 | if max < j-i { 37 | max = j - i 38 | ret = s[i : j+1] 39 | } 40 | } 41 | } 42 | } 43 | return ret 44 | } 45 | -------------------------------------------------------------------------------- /problem/524.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | ### 题目: 5 | 6 | > 给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串可以通过删除给定字符串的某些字符来得到。如果答案不止一个,返回长度最长且字典顺序最小的字符串。如果答案不存在,则返回空字符串。 7 | 8 | 9 | #### 示例1: 10 | 11 | ``` 12 | 输入: 13 | s = "abpcplea", d = ["ale","apple","monkey","plea"] 14 | 15 | 输出: 16 | "apple" 17 | 18 | ``` 19 | 20 | #### 示例2: 21 | 22 | ``` 23 | 输入: 24 | s = "abpcplea", d = ["a","b","c"] 25 | 26 | 输出: 27 | "a" 28 | ``` 29 | 30 | 31 | ### 解析题目: 32 | 33 | 以示例1来说, 比如 `ale`来匹配 `s`,先把 `a`字母放到`s`里找,发现`s`里第一个就是,那么,按照顺序,开始用`l`来找,且在`s`里第二个开始找(因为顺序是固定的),发现在`s`的下标5处找到了`l`,然后开始用`e`来找且从`s`下标5后面开始找,发现`s`下标6就是`e`,然后`ale`全部找到了,那么说明 `ale`是答案之一,`apple`同理,到`monkey`的时候,先用`m`在`s`里找,发现`s`里一个`m`都木有,那么,`monkey`肯定不匹配 34 | 35 | 36 | 首先要注意,可能字符串是空,或者字典也可能是空的 37 | 38 | 其次, 符合的答案可能是多个,那么,多个的时候,先按照长度最长判断,长度相同的时候,按照`字典序`最小的! 注意这个`字典序`并不是 上面示例中的 `d`数组里的value所对应的 `key`,字典序是按照 字母的顺序排列的, 比如 `a` 肯定是在 `c` 前面的! 39 | 40 | 因为我是用`Golang`解题,那么,`Golang`的 `sort`字符串排序就是按照字典顺序排列的! 41 | 42 | 43 | 44 | ### 思路: 45 | 46 | 大致解法1: 粗暴的拿`d`里的每个字符串的每个字母依次跟 `s`的每个字母进行比较! 不过得注意顺序 47 | 48 | 大致解法2: 根据`d`的字符串的每个字母在`s`里进行匹配,`s`里多余的都删掉,得最后结果 49 | 50 | 大致解法3: 反正题目没有要求,来个正则吧,符合正则匹配的,都撸出来! 51 | 52 | */ 53 | 54 | func findLongestWord(s string, d []string) string { 55 | if s == "" || len(d) == 0 { 56 | return "" 57 | } 58 | var res string 59 | for _, v := range d { 60 | // 如果字典字符串比s还要长,那么肯定匹配不上 61 | if len(v) > len(s) { 62 | continue 63 | } 64 | i := 0 65 | j := 0 66 | for i < len(v) && j < len(s) { 67 | if v[i] == s[j] { 68 | // 当匹配到一个字符后,如果后面的长度比被匹配的还要长,那么肯定匹配不上 69 | if len(v[i:]) > len(s[j:]) { 70 | break 71 | } 72 | i++ 73 | } 74 | j++ 75 | } 76 | // 如果i 等于v的长度,说明 v已经完全匹配了,那么说明它肯定是s的子集 77 | if i == len(v) { 78 | // 比较之前最符合的子集长度与此次的相比 79 | if len(v) == len(res) { 80 | // 直接按照 大小比字典顺序 81 | if v < res { 82 | res = v 83 | } 84 | } else if len(v) > len(res) { 85 | res = v 86 | } 87 | } 88 | } 89 | 90 | return res 91 | } 92 | -------------------------------------------------------------------------------- /problem/53.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 5 | 6 | 示例: 7 | 8 | 输入: [-2,1,-3,4,-1,2,1,-5,4], 9 | 输出: 6 10 | 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 11 | */ 12 | 13 | func maxSubArray(nums []int) int { 14 | if len(nums) == 0 { 15 | return 0 16 | } 17 | if len(nums) == 1 { 18 | return nums[0] 19 | } 20 | ret := make([]int, len(nums)) 21 | ret[0] = nums[0] 22 | max := ret[0] 23 | for i := 1; i < len(nums); i++ { 24 | tmp := ret[i-1] + nums[i] 25 | if tmp > nums[i] { 26 | ret[i] = tmp 27 | } else { 28 | ret[i] = nums[i] 29 | } 30 | if max < ret[i] { 31 | max = ret[i] 32 | } 33 | } 34 | return max 35 | } 36 | -------------------------------------------------------------------------------- /problem/547.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。 5 | 6 | 给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。 7 | 8 | 示例 1: 9 | 10 | 输入: 11 | [[1,1,0], 12 | [1,1,0], 13 | [0,0,1]] 14 | 输出: 2 15 | 说明:已知学生0和学生1互为朋友,他们在一个朋友圈。 16 | 第2个学生自己在一个朋友圈。所以返回2。 17 | 示例 2: 18 | 19 | 输入: 20 | [[1,1,0], 21 | [1,1,1], 22 | [0,1,1]] 23 | 输出: 1 24 | 说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。 25 | 注意: 26 | 27 | N 在[1,200]的范围内。 28 | 对于所有学生,有M[i][i] = 1。 29 | 如果有M[i][j] = 1,则有M[j][i] = 1。 30 | */ 31 | 32 | func findCircleNum(M [][]int) int { 33 | m := make(map[int]int, len(M)) 34 | count := 0 35 | for i:=0;i m[j][0] { 27 | return false 28 | } 29 | return true 30 | } 31 | 32 | func (m MS) Swap(i, j int) { 33 | m[i], m[j] = m[j], m[i] 34 | } 35 | 36 | func max(i, j int) int { 37 | if i > j { 38 | return i 39 | } 40 | return j 41 | } 42 | 43 | func merge(intervals [][]int) [][]int { 44 | s := len(intervals) 45 | ret := make([][]int, 0) 46 | if s == 0 { 47 | return ret 48 | } 49 | sort.Sort(MS(intervals)) 50 | tmp := intervals[0] 51 | for j := 1; j < s; j++ { 52 | if tmp[1] >= intervals[j][0] { 53 | tmp[1] = max(tmp[1], intervals[j][1]) 54 | } else { 55 | ret = append(ret, tmp) 56 | tmp = intervals[j] 57 | } 58 | } 59 | ret = append(ret, tmp) 60 | return ret 61 | } 62 | -------------------------------------------------------------------------------- /problem/61.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。 5 | 6 | 示例 1: 7 | 8 | 输入: 1->2->3->4->5->NULL, k = 2 9 | 输出: 4->5->1->2->3->NULL 10 | 解释: 11 | 向右旋转 1 步: 5->1->2->3->4->NULL 12 | 向右旋转 2 步: 4->5->1->2->3->NULL 13 | 示例 2: 14 | 15 | 输入: 0->1->2->NULL, k = 4 16 | 输出: 2->0->1->NULL 17 | 解释: 18 | 向右旋转 1 步: 2->0->1->NULL 19 | 向右旋转 2 步: 1->2->0->NULL 20 | 向右旋转 3 步: 0->1->2->NULL 21 | 向右旋转 4 步: 2->0->1->NULL 22 | */ 23 | 24 | func rotateRight(head *ListNode, k int) *ListNode { 25 | if head == nil { 26 | return nil 27 | } 28 | newHead := head 29 | length := 1 30 | for head.Next != nil { 31 | length++ 32 | head = head.Next 33 | } 34 | head.Next = newHead 35 | newPos := length - k%length 36 | for i := 1; i < newPos; i++ { 37 | newHead = newHead.Next 38 | } 39 | res := newHead.Next 40 | newHead.Next = nil 41 | return res 42 | 43 | } 44 | -------------------------------------------------------------------------------- /problem/63.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 5 | 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 6 | 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 7 | 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径? 8 | 网格中的障碍物和空位置分别用 1 和 0 来表示。 9 | 说明:m 和 n 的值均不超过 100。 10 | 11 | 示例 1: 12 | 输入: 13 | [ 14 |   [0,0,0], 15 |   [0,1,0], 16 |   [0,0,0] 17 | ] 18 | 输出: 2 19 | 解释: 20 | 3x3 网格的正中间有一个障碍物。 21 | 从左上角到右下角一共有 2 条不同的路径: 22 | 1. 向右 -> 向右 -> 向下 -> 向下 23 | 2. 向下 -> 向下 -> 向右 -> 向右 24 | 25 | */ 26 | func uniquePathsWithObstacles(obstacleGrid [][]int) int { 27 | if (len(obstacleGrid) == 0) { 28 | return 0; 29 | } 30 | if (obstacleGrid[0][0] == 1) { 31 | return 0; 32 | } 33 | obstacleGrid[0][0] = 1 34 | for i := 1; i < len(obstacleGrid); i++ { 35 | if obstacleGrid[i][0] == 1 { 36 | obstacleGrid[i][0] = 0 37 | } else { 38 | obstacleGrid[i][0] = obstacleGrid[i - 1][0] 39 | } 40 | } 41 | for j := 1; j < len(obstacleGrid[0]); j++ { 42 | if obstacleGrid[0][j] == 1 { 43 | obstacleGrid[0][j] = 0 44 | } else { 45 | obstacleGrid[0][j] = obstacleGrid[0][j-1] 46 | } 47 | } 48 | for m := 1; m < len(obstacleGrid); m++ { 49 | for n := 1; n < len(obstacleGrid[0]); n++ { 50 | if obstacleGrid[m][n] == 1{ 51 | obstacleGrid[m][n] = 0 52 | }else{ 53 | obstacleGrid[m][n] = obstacleGrid[m-1][n] + obstacleGrid[m][n-1] 54 | } 55 | } 56 | } 57 | return obstacleGrid[len(obstacleGrid)-1][len(obstacleGrid[0])-1] 58 | } 59 | -------------------------------------------------------------------------------- /problem/7.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import "math" 4 | 5 | /* 6 | 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 7 | 8 | 示例 1: 9 | 输入: 123 10 | 输出: 321 11 | 12 | 示例 2: 13 | 输入: -123 14 | 输出: -321 15 | 16 | 示例 3: 17 | 输入: 120 18 | 输出: 21 19 | */ 20 | 21 | func reverse(x int) int { 22 | y := 0 23 | for x != 0 { 24 | y = y*10 + x%10 25 | x = x / 10 26 | } 27 | if y > math.MaxInt32 || y < math.MinInt32 { 28 | return 0 29 | } 30 | return y 31 | } 32 | -------------------------------------------------------------------------------- /problem/713.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | func main() { 4 | arr := []int{10,5,2,6} 5 | numSubarrayProductLessThanK(arr, 100) 6 | } 7 | 8 | /* 9 | 给定一个正整数数组 nums。 10 | 11 | 找出该数组内乘积小于 k 的连续的子数组的个数。 12 | 13 | 示例 1: 14 | 15 | 输入: nums = [10,5,2,6], k = 100 16 | 输出: 8 17 | 解释: 8个乘积小于100的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。 18 | 需要注意的是 [10,5,2] 并不是乘积小于100的子数组。 19 | 说明: 20 | 21 | 0 < nums.length <= 50000 22 | 0 < nums[i] < 1000 23 | 0 <= k < 10^6 24 | 25 | 解题思路:取两个数的乘积,若小于k,值付给临时乘积,再取下一个值乘以当前乘积,若大于k,记录个数,跳出循环,当前乘积除以left初始位置的参数,left+1,此时当前乘积就等于第二个,第三个参数的乘积,以此类推 26 | */ 27 | 28 | func numSubarrayProductLessThanK(nums []int, k int) int { 29 | if (k <= 0 ) { 30 | return 0 31 | } 32 | var count = 0 //小于k的个数 33 | var left = 0 //开始位置 34 | var right = 0 //结束位置 35 | var multiplier = 1 //临时乘积 36 | var lenth = len(nums) //数组长度 37 | //从头开始循环遍历数组 38 | for left = 0; left < lenth; left ++ { 39 | 40 | for right < lenth && multiplier*nums[right] < k { 41 | 42 | multiplier *= nums[right] 43 | right++ 44 | } 45 | if left == right { 46 | right++ 47 | } else { 48 | count += right - left 49 | multiplier /= nums[left] 50 | } 51 | } 52 | return count 53 | 54 | } -------------------------------------------------------------------------------- /problem/72.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。 5 | 6 | 你可以对一个单词进行如下三种操作: 7 | 8 | 插入一个字符 9 | 删除一个字符 10 | 替换一个字符 11 | 示例 1: 12 | 13 | 输入: word1 = "horse", word2 = "ros" 14 | 输出: 3 15 | 解释: 16 | horse -> rorse (将 'h' 替换为 'r') 17 | rorse -> rose (删除 'r') 18 | rose -> ros (删除 'e') 19 | 示例 2: 20 | 21 | 输入: word1 = "intention", word2 = "execution" 22 | 输出: 5 23 | 解释: 24 | intention -> inention (删除 't') 25 | inention -> enention (将 'i' 替换为 'e') 26 | enention -> exention (将 'n' 替换为 'x') 27 | exention -> exection (将 'n' 替换为 'c') 28 | exection -> execution (插入 'u') 29 | 30 | */ 31 | func minDistance(word1 string, word2 string) int { 32 | var min func(a, b int) int 33 | min = func(a, b int) int { 34 | if a < b { 35 | return a 36 | } 37 | return b 38 | } 39 | 40 | word1Len, word2Len := len(word1), len(word2) 41 | if word1Len*word2Len == 0 { 42 | return word1Len + word2Len 43 | } 44 | 45 | dis := make([][]int, word1Len+1) 46 | for i := 0; i < word1Len+1; i++ { 47 | dis[i] = make([]int, word2Len+1) 48 | } 49 | for i := 0; i < word1Len+1; i++ { 50 | dis[i][0] = i 51 | } 52 | for j := 0; j < word2Len+1; j++ { 53 | dis[0][j] = j 54 | } 55 | 56 | for i := 1; i < word1Len+1; i++ { 57 | for j := 1; j < word2Len+1; j++ { 58 | if word1[i-1] == word2[j-1] { 59 | dis[i][j] = min(min(dis[i-1][j], dis[i][j-1]), dis[i-1][j-1]-1) + 1 60 | } else { 61 | dis[i][j] = min(min(dis[i-1][j], dis[i][j-1]), dis[i-1][j-1]) + 1 62 | } 63 | } 64 | } 65 | return dis[word1Len][word2Len] 66 | } 67 | -------------------------------------------------------------------------------- /problem/75.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 5 | 6 | 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 7 | 8 | 注意: 9 | 不能使用代码库中的排序函数来解决这道题。 10 | 11 | 示例: 12 | 13 | 输入: [2,0,2,1,1,0] 14 | 输出: [0,0,1,1,2,2] 15 | 进阶: 16 | 17 | 一个直观的解决方案是使用计数排序的两趟扫描算法。 18 | 首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。 19 | 你能想出一个仅使用常数空间的一趟扫描算法吗? 20 | */ 21 | func sortColors(nums []int) { 22 | if len(nums) == 0 { 23 | return 24 | } 25 | p0 := 0 26 | p2 := len(nums) - 1 27 | curr := 0 28 | for curr <= p2 { 29 | switch nums[curr] { 30 | case 0: 31 | nums[p0],nums[curr] = nums[curr],nums[p0] 32 | p0++ 33 | curr++ 34 | case 1: 35 | curr++ 36 | case 2: 37 | nums[p2],nums[curr] = nums[curr],nums[p2] 38 | p2-- 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /problem/767.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | /*给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。 9 | 10 | 若可行,输出任意可行的结果。若不可行,返回空字符串。 11 | 12 | 示例 1: 13 | 14 | 输入: S = "aab" 15 | 输出: "aba" 16 | 17 | 示例 2: 18 | 19 | 输入: S = "aaab" 20 | 输出: "" 21 | 22 | 注意: 23 | 24 | S 只包含小写字母并且长度在[1, 500]区间内。*/ 25 | 26 | /* 思路 27 | 1.出现次数最多的字符数不大于(n+1)/2 max<=(n+1)/2 28 | 2.提取k=>v,字符=>出现次数 29 | 3.每次从字符数排名前两位的字符中取字符,字符数相等时,避免,ab,ba,ab 情况出现 30 | 4.依次取出两个,直到取完为止*/ 31 | 32 | type CharNum struct { 33 | char string 34 | num int 35 | } 36 | 37 | type CharNums []CharNum 38 | 39 | //Len() 40 | func (s CharNums) Len() int { 41 | return len(s) 42 | } 43 | 44 | //Less():排序 45 | func (s CharNums) Less(i, j int) bool { 46 | return s[i].num > s[j].num 47 | } 48 | 49 | //Swap() 50 | func (s CharNums) Swap(i, j int) { 51 | s[i], s[j] = s[j], s[i] 52 | } 53 | 54 | func getMaxNumChar(m map[string]int) (maxFirstChar, maxSecondChar string) { 55 | //重新生成二维数据结构 56 | var newStructs CharNums 57 | for k, v := range m { 58 | if v > 0 { 59 | newStructs = append(newStructs, CharNum{k, v}) 60 | } 61 | } 62 | //倒序 63 | sort.Sort(newStructs) 64 | 65 | fmt.Println(newStructs) 66 | 67 | var v1, v2 int 68 | for k, v := range newStructs { 69 | if k == 0 { 70 | v1 = v.num 71 | maxFirstChar = v.char 72 | } else if k == 1 { 73 | v2 = v.num 74 | maxSecondChar = v.char 75 | } else { 76 | break 77 | } 78 | } 79 | 80 | //num 相当时,保持输出字符顺序不变 81 | if v1 == v2 { 82 | if maxSecondChar > maxFirstChar { 83 | maxFirstChar, maxSecondChar = maxSecondChar, maxFirstChar 84 | } 85 | } 86 | 87 | return 88 | } 89 | 90 | func reorganizeString(S string) string { 91 | 92 | m := make(map[string]int, 26) 93 | 94 | for i := 0; i < len(S); i++ { 95 | m[string(S[i])] ++ 96 | } 97 | 98 | maxChar, _ := getMaxNumChar(m) 99 | 100 | if m[maxChar] > (len(S)+1)/2 { 101 | return "" 102 | } 103 | 104 | var newStr string 105 | for j := 0; j < len(S)/2+1; j++ { 106 | maxFirstChar, maxSecondChar := getMaxNumChar(m) 107 | newStr += maxFirstChar 108 | newStr += maxSecondChar 109 | m[maxFirstChar] -- 110 | m[maxSecondChar] -- 111 | } 112 | 113 | return newStr 114 | } 115 | -------------------------------------------------------------------------------- /problem/84.go: -------------------------------------------------------------------------------- 1 | package problem84 2 | 3 | /* 4 | 下面为了好理解,所以将步骤 拆解 分离 5 | 6 | */ 7 | func largestRectangleArea(heights []int) int { 8 | ma := 0 9 | if len(heights) < 0 { 10 | return 0 11 | } 12 | 13 | var stack []int 14 | for i := 0; i < len(heights); i++ { 15 | if i == 0 { 16 | stack = append(stack, heights[i]) 17 | m := maxArea(stack) 18 | ma = max(m, ma) 19 | continue 20 | } 21 | 22 | if heights[i-1] > heights[i] { 23 | m := maxArea(stack) 24 | ma = max(m, ma) 25 | stack = changeStack(stack, heights[i]) 26 | } 27 | 28 | stack = append(stack, heights[i]) 29 | 30 | if i+1 == len(heights) { 31 | m := maxArea(stack) 32 | ma = max(m, ma) 33 | continue 34 | } 35 | } 36 | 37 | return ma 38 | } 39 | 40 | func maxArea(h []int) int { 41 | ma := 0 42 | if len(h) == 1 { 43 | ma = h[0] 44 | } 45 | for i := 0; i < len(h); i++ { 46 | m := h[i] * (len(h) - i) 47 | ma = max(m, ma) 48 | } 49 | return ma 50 | } 51 | 52 | func max(a, b int) int { 53 | if a > b { 54 | return a 55 | } 56 | return b 57 | } 58 | 59 | func changeStack(s []int, insert int) []int { 60 | if len(s) == 0 { 61 | return append(s, insert) 62 | } 63 | for i := (len(s) - 1); i >= 0; i-- { 64 | if s[i] > insert { 65 | s[i] = insert 66 | } 67 | } 68 | 69 | return s 70 | } 71 | -------------------------------------------------------------------------------- /problem/843.go: -------------------------------------------------------------------------------- 1 | package problem 2 | /* 3 | 我们给出了一个由一些独特的单词组成的单词列表,每个单词都是 6 个字母长,并且这个列表中的一个单词将被选作秘密。 4 | 你可以调用 master.guess(word) 来猜单词。你所猜的单词应当是存在于原列表并且由 6 个小写字母组成的类型字符串。 5 | 此函数将会返回一个整型数字,表示你的猜测与秘密单词的准确匹配(值和位置同时匹配)的数目。此外,如果你的猜测不在给定的单词列表中,它将返回 -1。 6 | 对于每个测试用例,你有 10 次机会来猜出这个单词。当所有调用都结束时,如果您对 master.guess 的调用不超过 10 次,并且至少有一次猜到秘密,那么您将通过该测试用例。 7 | 除了下面示例给出的测试用例外,还会有 5 个额外的测试用例,每个单词列表中将会有 100 个单词。 8 | 这些测试用例中的每个单词的字母都是从 'a' 到 'z' 中随机选取的,并且保证给定单词列表中的每个单词都是唯一的。 9 | 10 | 示例: 11 | 输入: secret = "acckzz", wordlist = ["acckzz","ccbazz","eiowzz","abcczz"] 12 | 13 | */ 14 | func cmp(sa, sb string) int { 15 | c := 0 16 | for i := 0; i < 6; i++ { 17 | if sa[i] == sb[i] { 18 | c++ 19 | } 20 | } 21 | return c 22 | } 23 | 24 | func findSecretWord(wordlist []string, master *Master) { 25 | l := len(wordlist) 26 | t := make([][]int, l) 27 | for i := 0; i < l; i++ { 28 | t[i] = make([]int, l) 29 | t[i][i] = 6 30 | } 31 | 32 | for i := 0; i < l; i++ { 33 | for j := i + 1; j < l; j++ { 34 | c := cmp(wordlist[i], wordlist[j]) 35 | t[i][j], t[j][i] = c, c 36 | } 37 | } 38 | 39 | m, j := l, 0 40 | for i := 0; i < l; i++ { 41 | cs, mc := [7]int{}, 0 42 | for _, j := range t[i] { 43 | cs[j]++ 44 | if cs[j] > mc { 45 | mc = cs[j] 46 | } 47 | } 48 | if mc < m { 49 | m, j = mc, i 50 | } 51 | } 52 | 53 | wg := wordlist[j] 54 | res := master.Guess(wg) 55 | if 6 != res { 56 | sub := []string{} 57 | for _, w := range wordlist { 58 | if w != wg && cmp(w, wg) == res { 59 | sub = append(sub, w) 60 | } 61 | } 62 | findSecretWord(sub, master) 63 | } 64 | } -------------------------------------------------------------------------------- /problem/85.go: -------------------------------------------------------------------------------- 1 | package problem85 2 | 3 | /* 4 | 此题 为84题的升级版 5 | */ 6 | func maximalRectangle(mat [][]byte) int { 7 | m := len(mat) 8 | if m == 0 { 9 | return 0 10 | } 11 | 12 | n := len(mat[0]) 13 | if n == 0 { 14 | return 0 15 | } 16 | 17 | dp := make([][]int, m) 18 | for i := 0; i < m; i++ { 19 | dp[i] = make([]int, n) 20 | } 21 | 22 | for j := 0; j < n; j++ { 23 | dp[0][j] = int(mat[0][j] - '0') 24 | for i := 1; i < m; i++ { 25 | if mat[i][j] == '1' { 26 | dp[i][j] = dp[i-1][j] + 1 27 | } 28 | } 29 | } 30 | max := 0 31 | for i := 0; i < m; i++ { 32 | tmp := largestRectangleArea(dp[i]) 33 | if max < tmp { 34 | max = tmp 35 | } 36 | } 37 | 38 | return max 39 | } 40 | 41 | // 从 84 题复制 42 | func largestRectangleArea(heights []int) int { 43 | ma := 0 44 | if len(heights) < 0 { 45 | return 0 46 | } 47 | 48 | var stack []int 49 | for i := 0; i < len(heights); i++ { 50 | if i == 0 { 51 | stack = append(stack, heights[i]) 52 | m := maxArea(stack) 53 | ma = max(m, ma) 54 | continue 55 | } 56 | 57 | if heights[i-1] > heights[i] { 58 | m := maxArea(stack) 59 | ma = max(m, ma) 60 | stack = changeStack(stack, heights[i]) 61 | } 62 | 63 | stack = append(stack, heights[i]) 64 | 65 | if i+1 == len(heights) { 66 | m := maxArea(stack) 67 | ma = max(m, ma) 68 | continue 69 | } 70 | } 71 | 72 | return ma 73 | } 74 | 75 | func maxArea(h []int) int { 76 | ma := 0 77 | if len(h) == 1 { 78 | ma = h[0] 79 | } 80 | for i := 0; i < len(h); i++ { 81 | m := h[i] * (len(h) - i) 82 | ma = max(m, ma) 83 | } 84 | return ma 85 | } 86 | 87 | func max(a, b int) int { 88 | if a > b { 89 | return a 90 | } 91 | return b 92 | } 93 | 94 | func changeStack(s []int, insert int) []int { 95 | if len(s) == 0 { 96 | return append(s, insert) 97 | } 98 | for i := (len(s) - 1); i >= 0; i-- { 99 | if s[i] > insert { 100 | s[i] = insert 101 | } 102 | } 103 | 104 | return s 105 | } 106 | -------------------------------------------------------------------------------- /problem/86.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。 5 | 6 | 你应当保留两个分区中每个节点的初始相对位置。 7 | 8 | 示例: 9 | 10 | 输入: head = 1->4->3->2->5->2, x = 3 11 | 输出: 1->2->2->4->3->5 12 | 13 | */ 14 | func partition(head *ListNode, x int) *ListNode { 15 | if head == nil { 16 | return head 17 | } 18 | 19 | root := &ListNode{Next: head} 20 | small := root 21 | pre := root 22 | curr := head 23 | for curr != nil { 24 | if curr.Val < x { 25 | pre.Next = curr.Next 26 | tmp := small.Next 27 | small.Next = curr 28 | curr.Next = tmp 29 | small = small.Next 30 | } 31 | pre = curr 32 | curr = curr.Next 33 | } 34 | return root.Next 35 | } 36 | -------------------------------------------------------------------------------- /problem/93.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 93. 复原IP地址 5 | 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。 6 | 7 | 示例: 8 | 9 | 输入: "25525511135" 10 | 输出: ["255.255.11.135", "255.255.111.35"] 11 | 12 | 13 | 链接:https://leetcode-cn.com/problems/restore-ip-addresses 14 | 15 | */ 16 | func restoreIpAddresses(s string) []string { 17 | var ipAddress []string 18 | //先判断字符串长度是否合法 19 | if len(s) < 4 { 20 | return ipAddress 21 | } 22 | //循环校验IP地址是否合法 23 | for x := 1; x <= 3 && x <= len(s)-3; x++ { 24 | if !checkIP(s[:x]) { 25 | continue 26 | } 27 | //第二位数 28 | for y := 1; y <= 3 && y <= len(s)-x-2; y++ { 29 | if !checkIP(s[x : x+y]) { 30 | continue 31 | } 32 | //第三位数 33 | for z := 1; z <= 3 && z <= len(s)-x-y-1; z++ { 34 | if !checkIP(s[x+y:x+y+z]) || !checkIP(s[x+y+z:]) { 35 | continue 36 | } 37 | ip := s[:x] + "." + s[x:x+y] + "." + s[x+y:x+y+z] + "." + s[x+y+z:] 38 | ipAddress = append(ipAddress, ip) 39 | } 40 | } 41 | } 42 | 43 | return ipAddress 44 | } 45 | 46 | func checkIP(str string) bool { 47 | switch len(str) { 48 | case 3: 49 | return str >= "100" && str <= "255" 50 | case 2: 51 | return str >= "10" && str <= "99" 52 | case 1: 53 | return true 54 | default: 55 | return false 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /problem/97.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | /* 4 | 给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。 5 | 6 | 示例 1: 7 | 8 | 输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" 9 | 输出: true 10 | 示例 2: 11 | 12 | 输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" 13 | 输出: false 14 | 15 | 解题思路1:递归,分别取出s1和s2的每隔一个字符,如果s1或s2的最前面的字符和s3最前面的字符相同,则返回s1或s2的当前字符之后的字符串,再递归进行对比,直到s1和s2两个字符串的字符都为空,这个时候就返回true,否则返回false 16 | 17 | 阶梯思路2:动态规划,s1的前i个元素加上s2的前j个元素,等于s3的前i+j个元素,从题目来看假设从dp[0][0]的位置开始,走到dp[5][5]的位置,假如某个位置返回为真,那它的左边位置或者上边位置的值也同样为真,那它左边的位置就等于dp[i][j-1],和s3[i+j-1]的位置进行对比,如果为真,就是左边的路径为真,如果为假,那我们走上边的位置,等于dp[i-1][j],和[i+j-1]的位置进行对比,这两个对比,其中某一个为真,那最终的结果就是为真。看图 18 | 19 | 图中从[0][0]的位置开始找,与s3[0][0]进行对比,直到s[5][5]的位置 20 | 21 | d b b c a 22 | 0 1 2 3 4 5 23 | —————————————— 24 | 0| 1 0 0 0 0 0 25 | a 1| 1 0 0 0 0 0 26 | a 2| 1 1 1 1 1 0 27 | b 3| 0 1 1 0 1 0 28 | c 4| 0 0 1 1 1 1 29 | c 5| 0 0 0 1 0 1 30 | */ 31 | 32 | 33 | func main() { 34 | s1 := "aabcc" 35 | s2 := "dbbca" 36 | s3 := "aadbbcbcac" 37 | isInterleave(s1, s2, s3) 38 | isInterleave2(s1, s2, s3) 39 | 40 | } 41 | //动态规划 42 | func isInterleave(s1 string, s2 string, s3 string) bool { 43 | len1 := len(s1) 44 | len2 := len(s2) 45 | len3 := len(s3) 46 | 47 | if len1+len2 != len3 { 48 | return false 49 | } 50 | s1b := []byte(s1) 51 | s2b := []byte(s2) 52 | s3b := []byte(s3) 53 | 54 | dp := make([][]bool, len(s2)+1) 55 | 56 | for i := 0; i < len(dp); i++ { 57 | dp[i] = make([]bool, len(s1)+1) 58 | } 59 | 60 | for i := 0; i <= len2; i++ { 61 | for j := 0; j <= len1; j++ { 62 | 63 | if i == 0 && j == 0 { 64 | dp[i][j] = true 65 | } else if i == 0 { 66 | dp[i][j] = dp[i][j-1] && s1b[j-1] == s3b[j-1] 67 | } else if j == 0 { 68 | dp[i][j] = dp[i-1][j] && s2b[i-1] == s3b[i-1] 69 | } else { 70 | dp[i][j] = (dp[i-1][j] && s2b[i-1] == s3b[i+j-1]) || (dp[i][j-1] && s1b[j-1] == s3b[i+j-1]) 71 | } 72 | } 73 | } 74 | return dp[len(s2)][len(s1)] 75 | } 76 | 77 | //递归 78 | func isInterleave2(s1 string, s2 string, s3 string) bool { 79 | if (len(s1) + len(s2)) != len(s3) { 80 | return false 81 | } 82 | if s1 == "" && s2 == "" { 83 | return true 84 | } else if (s1 == "") { 85 | if s2[0] == s3[0] { 86 | return isInterleave(s1, s2[1:], s3[1:]) 87 | } 88 | } else if (s2 == "") { 89 | if s1[0] == s3[0] { 90 | return isInterleave(s1[1:], s2, s3[1:]) 91 | } 92 | } 93 | if (s1 != "" && s1[0] == s3[0] && s2[0] != s3[0]) { 94 | return isInterleave(s1[1:], s2, s3[1:]) 95 | } else if (s2 != "" && s2[0] == s3[0] && s1[0] != s3[0]) { 96 | 97 | return isInterleave(s1, s2[1:], s3[1:]) 98 | } else if (s1 != "" && s1[0] == s3[0] && s2 != "" && s2[0] == s3[0]) { 99 | 100 | isRel := isInterleave(s1[1:], s2, s3[1:]) 101 | isRel2 := isInterleave(s1, s2[1:], s3[1:]) 102 | if isRel || isRel2 { 103 | return true 104 | } else { 105 | return false 106 | } 107 | } else { 108 | return false 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /problem/98.go: -------------------------------------------------------------------------------- 1 | package problem 2 | 3 | import "math" 4 | 5 | /*给定一个二叉树,判断其是否是一个有效的二叉搜索树。 6 | 7 | 假设一个二叉搜索树具有如下特征: 8 | 9 | 节点的左子树只包含小于当前节点的数。 10 | 节点的右子树只包含大于当前节点的数。 11 | 所有左子树和右子树自身必须也是二叉搜索树。 12 | 示例 1: 13 | 14 | 输入: 15 | 2 16 | / \ 17 | 1 3 18 | 输出: true 19 | 示例 2: 20 | 21 | 输入: 22 | 5 23 | / \ 24 | 1 4 25 | / \ 26 | 3 6 27 | 输出: false 28 | 解释: 输入为: [5,1,4,null,null,3,6]。 29 | 根节点的值为 5 ,但是其右子节点值为 4 。 30 | */ 31 | 32 | func isValidBST(root *TreeNode) bool { 33 | return isValid(root, math.MinInt64, math.MaxInt64) 34 | } 35 | 36 | func isValid(root *TreeNode, min, max int) bool { 37 | if root == nil { 38 | return true 39 | } 40 | if root.Val <= min { 41 | return false 42 | } 43 | if root.Val >= max { 44 | return false 45 | } 46 | return isValid(root.Left, min, root.Val) && isValid(root.Right, root.Val, max) 47 | } 48 | --------------------------------------------------------------------------------