diff --git a/.github/workflows/restructure_files.yml b/.github/workflows/restructure_files.yml index d510109..d0b6311 100644 --- a/.github/workflows/restructure_files.yml +++ b/.github/workflows/restructure_files.yml @@ -3,8 +3,6 @@ name: Restructure files on: push: branches: [ main ] - pull_request: - branches: [ main ] workflow_dispatch: jobs: diff --git a/README.md b/README.md index 3b8540f..2c0cd4e 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ 所以基地里的题解都尽量用动画模拟,加深大家对题目的理解。往下看吧 -另外因为一个人的精力有限,所以基地目前只有 JAVA 代码,欢迎大家贡献其他版本代码。 +另外因为一个人的精力有限,所以基地目前只有 JAVA 代码,欢迎大家[贡献其他版本代码]() 贡献仓库注意事项 @@ -43,7 +43,7 @@ 如果老哥觉得仓库很用心的话,麻烦大佬帮忙点个 star ,这也是我们一直更新下去的动力。 -感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助, +感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助. > 另外我和几位老哥,给刚开始刷题,但是不知道从哪里开始刷的同学,整理了一份 【刷题大纲 】可以先按这个顺序刷,刷完之后应该就能入门,当然该仓库的大部分题解也是来自那个大纲。 > @@ -153,7 +153,7 @@ - [【动画模拟】leetcode 27 移除元素](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E6%95%B0%E7%BB%84%E7%AF%87/leetcode27%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.md) - [【动画模拟】leetcode 209 长度最小的子数组](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E6%95%B0%E7%BB%84%E7%AF%87/%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.md) - [【动画模拟】leetcode 141 环形链表](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/leetcode141%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8.md) -- [【动画模拟】leetcode 160 相交链表](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/leetcode%E7%9B%B8%E4%BA%A4%E9%93%BE%E8%A1%A8.md) +- [【动画模拟】剑指 offer 52 两个链表的第一个公共节点 & leetcode 160 相交链表](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/%E5%89%91%E6%8C%87Offer52%E4%B8%A4%E4%B8%AA%E9%93%BE%E8%A1%A8%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%85%AC%E5%85%B1%E8%8A%82%E7%82%B9.md) - [【动画模拟】leetcode 328 奇偶链表](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/leetcode328%E5%A5%87%E5%81%B6%E9%93%BE%E8%A1%A8.md) ### 🏳‍🌈 栈和队列 diff --git a/animation-simulation/二分查找及其变种/leetcode 81不完全有序查找目标元素(包含重复值) .md b/animation-simulation/二分查找及其变种/leetcode 81不完全有序查找目标元素(包含重复值) .md index 2964fe2..206fff5 100644 --- a/animation-simulation/二分查找及其变种/leetcode 81不完全有序查找目标元素(包含重复值) .md +++ b/animation-simulation/二分查找及其变种/leetcode 81不完全有序查找目标元素(包含重复值) .md @@ -76,36 +76,4 @@ class Solution { } ``` -Go Code: -```go -func search(nums []int, target int) bool { - left := 0 - right := len(nums) - 1 - for (left <= right) { - mid := left+((right-left)>>1) - if (nums[mid] == target) { - return true - } - if (nums[mid] == nums[left]) { - left++ - continue - } - if (nums[mid] > nums[left]) { - if (nums[mid] > target && target >= nums[left]) { - right = mid - 1 - } else if (target > nums[mid] || target < nums[left]) { - left = mid + 1 - } - - }else if (nums[mid] < nums[left]) { - if (nums[mid] < target && target <= nums[right]) { - left = mid + 1 - } else if (target < nums[mid] || target > nums[right]) { - right = mid - 1 - } - } - } - return false -} -``` diff --git a/animation-simulation/二分查找及其变种/leetcode153搜索旋转数组的最小值.md b/animation-simulation/二分查找及其变种/leetcode153搜索旋转数组的最小值.md index d705ef4..516e5a9 100644 --- a/animation-simulation/二分查找及其变种/leetcode153搜索旋转数组的最小值.md +++ b/animation-simulation/二分查找及其变种/leetcode153搜索旋转数组的最小值.md @@ -105,25 +105,3 @@ public: }; ``` -Go Code: - -```go -func findMin(nums []int) int { - left := 0 - right := len(nums) - 1 - - for (left < right) { - - if (nums[left] < nums[right]) { - return nums[left] - } - mid := left + ((right - left) >> 1) - if (nums[left] > nums[mid]) { - right = mid - } else { - left = mid + 1 - } - } - return nums[left] -} -``` diff --git a/animation-simulation/二分查找及其变种/leetcode33不完全有序查找目标元素(不包含重复值).md b/animation-simulation/二分查找及其变种/leetcode33不完全有序查找目标元素(不包含重复值).md index 78d4f75..db6d2fc 100644 --- a/animation-simulation/二分查找及其变种/leetcode33不完全有序查找目标元素(不包含重复值).md +++ b/animation-simulation/二分查找及其变种/leetcode33不完全有序查找目标元素(不包含重复值).md @@ -129,39 +129,3 @@ class Solution { } ``` -Go Code: - -```go -func search(nums []int, target int) int { - // 左右指针 - left := 0 - right := len(nums) - 1 - for (left <= right) { - mid := left + ((right - left) >> 1) - rightNum, leftNum, midNum := nums[right], nums[left], nums[mid] - if midNum == target { - return mid - } - - //落在同一数组的情况,同时落在数组1 或 数组2 - if midNum >= leftNum { - //target 落在 left 和 mid 之间,则移动我们的right,完全有序的一个区间内查找 - if midNum > target && target >= leftNum { - right = mid - 1 - } else { - // target落在另一个无序区间, 但和原数组的性质相符, 所以可以继续循环 - left = mid + 1 - } - } else { - //target 落在 mid 和 right 之间,则移动我们的left,完全有序的一个区间内查找 - if midNum < target && target <= rightNum { - left = mid + 1 - } else { - // target落在另一个无序区间, 但和原数组的性质相符, 所以可以继续循环 - right = mid - 1 - } - } - } - return -1 -} -``` diff --git a/animation-simulation/二分查找及其变种/leetcode34查找第一个位置和最后一个位置.md b/animation-simulation/二分查找及其变种/leetcode34查找第一个位置和最后一个位置.md index 2e62413..0a43f40 100644 --- a/animation-simulation/二分查找及其变种/leetcode34查找第一个位置和最后一个位置.md +++ b/animation-simulation/二分查找及其变种/leetcode34查找第一个位置和最后一个位置.md @@ -169,48 +169,3 @@ class Solution { } ``` -Go Code: - -```go -func searchRange(nums []int, target int) []int { - upper := upperBound(nums, target) - low := lowerBound(nums, target) - // 不存在情况 - if (upper < low) { - return []int{-1, -1} - } - - return []int{low, upper} -} - -//计算下边界 -func lowerBound(nums []int, target int) int { - left, right := 0, len(nums) - 1 - for (left <= right) { - //这里需要注意,计算mid - mid := left + ((right - left) >> 1) - if (target <= nums[mid]) { - //当目标值小于等于nums[mid]时,继续在左区间检索,找到第一个数 - right = mid - 1 - - }else if (target > nums[mid]) { - //目标值大于nums[mid]时,则在右区间继续检索,找到第一个等于目标值的数 - left = mid + 1 - } - } - return left -} -//计算上边界 -func upperBound(nums []int, target int) int { - left, right := 0, len(nums) - 1 - for (left <= right) { - mid := left + ((right - left) >> 1) - if (target >= nums[mid]) { - left = mid + 1 - }else if (target < nums[mid]) { - right = mid - 1 - } - } - return right -} -``` diff --git a/animation-simulation/二分查找及其变种/leetcode35搜索插入位置.md b/animation-simulation/二分查找及其变种/leetcode35搜索插入位置.md index 531342a..142d4ce 100644 --- a/animation-simulation/二分查找及其变种/leetcode35搜索插入位置.md +++ b/animation-simulation/二分查找及其变种/leetcode35搜索插入位置.md @@ -1,4 +1,4 @@ -> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈 +> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈 > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 > @@ -70,23 +70,3 @@ class Solution { Go Code: -```go -func searchInsert(nums []int, target int) int { - left, right := 0, len(nums) - 1 - for (left <= right) { - mid := left + ((right - left) >> 1) - // 查询成功 - if nums[mid] == target { - return mid - // 右区间 - } else if nums[mid] < target { - left = mid + 1 - // 左区间 - } else { - right = mid - 1 - } - } - return left - -} -``` diff --git a/animation-simulation/二分查找及其变种/二维数组的二分查找.md b/animation-simulation/二分查找及其变种/二维数组的二分查找.md index c9ff418..ff41324 100644 --- a/animation-simulation/二分查找及其变种/二维数组的二分查找.md +++ b/animation-simulation/二分查找及其变种/二维数组的二分查找.md @@ -86,32 +86,3 @@ class Solution { } ``` -Go Code: - -```go -func searchMatrix(matrix [][]int, target int) bool { - if len(matrix) == 0 { - return false - } - // 行数 - row := len(matrix) - //列数 - col := len(matrix[0]) - // 行数 * 列数 - 1 为右指针 - left, right := 0, row * col - 1 - for (left <= right) { - mid := left + ((right - left) >> 1) - //将一维坐标变为二维坐标 - rownum := mid / col - colnum := mid % col - if matrix[rownum][colnum] == target { - return true - } else if matrix[rownum][colnum] > target { - right = mid - 1 - } else if matrix[rownum][colnum] < target { - left = mid + 1 - } - } - return false -} -``` diff --git a/animation-simulation/二叉树/二叉树中序遍历(迭代).md b/animation-simulation/二叉树/二叉树中序遍历(迭代).md index 7b58f4c..fbfb0eb 100644 --- a/animation-simulation/二叉树/二叉树中序遍历(迭代).md +++ b/animation-simulation/二叉树/二叉树中序遍历(迭代).md @@ -78,4 +78,30 @@ class Solution { } ``` +Go Code: + +```go +func inorderTraversal(root *TreeNode) []int { + res := []int{} + if root == nil { + return res + } + stk := []*TreeNode{} + cur := root + for len(stk) != 0 || cur != nil { + // 找到当前应该遍历的那个节点,并且把左子节点都入栈 + for cur != nil { + stk = append(stk, cur) + cur = cur.Left + } + // 没有左子节点,则开始执行出栈操作 + temp := stk[len(stk) - 1] + stk = stk[: len(stk) - 1] + res = append(res, temp.Val) + cur = temp.Right + } + return res +} +``` + ### diff --git a/animation-simulation/二叉树/二叉树基础.md b/animation-simulation/二叉树/二叉树基础.md index 49a76e2..36a7d23 100644 --- a/animation-simulation/二叉树/二叉树基础.md +++ b/animation-simulation/二叉树/二叉树基础.md @@ -426,6 +426,34 @@ class Solution { } ``` +Go Code: + +```go +func levelOrder(root *TreeNode) [][]int { + res := [][]int{} + if root == nil { + return res + } + // 初始化队列时,记得把root节点加进去。 + que := []*TreeNode{root} + for len(que) != 0 { + t := []int{} + // 这里一定要先求出来que的长度,因为在迭代的过程中,que的长度是变化的。 + l := len(que) + for i := 0; i < l; i++ { + temp := que[0] + que = que[1:] + // 子节点不为空,就入队 + if temp.Left != nil { que = append(que, temp.Left) } + if temp.Right != nil { que = append(que, temp.Right) } + t = append(t, temp.Val) + } + res = append(res, t) + } + return res +} +``` + 时间复杂度:O(n) 空间复杂度:O(n) 大家如果吃透了二叉树的层序遍历的话,可以顺手把下面几道题目解决掉,思路一致,甚至都不用拐弯 diff --git a/animation-simulation/二叉树/二叉树的前序遍历(栈).md b/animation-simulation/二叉树/二叉树的前序遍历(栈).md index a40de9b..1675589 100644 --- a/animation-simulation/二叉树/二叉树的前序遍历(栈).md +++ b/animation-simulation/二叉树/二叉树的前序遍历(栈).md @@ -95,3 +95,27 @@ class Solution { } } ``` + +Go Code: + +```go +func preorderTraversal(root *TreeNode) []int { + res := []int{} + if root == nil { + return res + } + stk := []*TreeNode{root} + for len(stk) != 0 { + temp := stk[len(stk) - 1] + stk = stk[: len(stk) - 1] + if temp.Right != nil { + stk = append(stk, temp.Right) + } + if temp.Left != nil { + stk = append(stk, temp.Left) + } + res = append(res, temp.Val) + } + return res +} +``` diff --git a/animation-simulation/二叉树/二叉树的后续遍历 (迭代).md b/animation-simulation/二叉树/二叉树的后续遍历 (迭代).md index 280c3e3..a7197a4 100644 --- a/animation-simulation/二叉树/二叉树的后续遍历 (迭代).md +++ b/animation-simulation/二叉树/二叉树的后续遍历 (迭代).md @@ -104,6 +104,36 @@ class Solution { } ``` +Go Code: + +```go +func postorderTraversal(root *TreeNode) []int { + res := []int{} + if root == nil { + return res + } + stk := []*TreeNode{} + cur := root + var pre *TreeNode + for len(stk) != 0 || cur != nil { + for cur != nil { + stk = append(stk, cur) + cur = cur.Left + } + // 这里符合本文最后的说法,使用先获取栈顶元素但是不弹出,根据栈顶元素的情况进行响应的处理。 + temp := stk[len(stk) - 1] + if temp.Right == nil || temp.Right == pre { + stk = stk[: len(stk) - 1] + res = append(res, temp.Val) + pre = temp + } else { + cur = temp.Right + } + } + return res +} +``` + 当然也可以修改下代码逻辑将 `cur = stack.pop()` 改成 `cur = stack.peek()`,下面再修改一两行代码也可以实现,这里这样写是方便动画模拟,大家可以随意发挥。 时间复杂度 O(n), 空间复杂度 O(n) diff --git a/animation-simulation/前缀和/leetcode523连续的子数组和.md b/animation-simulation/前缀和/leetcode523连续的子数组和.md index d458082..8662f2a 100644 --- a/animation-simulation/前缀和/leetcode523连续的子数组和.md +++ b/animation-simulation/前缀和/leetcode523连续的子数组和.md @@ -100,3 +100,35 @@ public: } }; ``` + +Go Code: + +```go +func checkSubarraySum(nums []int, k int) bool { + m := map[int]int{} + // 由于前缀和%k可能为0,所以需要给出没有元素的时候,索引位置,即-1 + m[0] = -1 + sum := 0 + for i, num := range nums { + sum += num + key := sum % k + /* + // 题目中告诉k >= 1 + key := sum + if k != 0 { + key = sum % k + } + */ + if v, ok := m[key]; ok { + if i - v >= 2 { + return true + } + // 避免更新最小索引 + continue + } + // 保存的是最小的索引 + m[key] = i + } + return false +} +``` diff --git a/animation-simulation/前缀和/leetcode560和为K的子数组.md b/animation-simulation/前缀和/leetcode560和为K的子数组.md index 60cb9b3..5464a2f 100644 --- a/animation-simulation/前缀和/leetcode560和为K的子数组.md +++ b/animation-simulation/前缀和/leetcode560和为K的子数组.md @@ -182,3 +182,24 @@ public: } }; ``` + +Go Code: + +```GO +func subarraySum(nums []int, k int) int { + m := map[int]int{} + // m存的是前缀和,没有元素的时候,和为0,且有1个子数组(空数组)满足条件,即m[0] = 1 + m[0] = 1 + sum := 0 + cnt := 0 + for _, num := range nums { + sum += num + if v, ok := m[sum - k]; ok { + cnt += v + } + // 更新满足前缀和的子数组数量 + m[sum]++ + } + return cnt +} +``` diff --git a/animation-simulation/前缀和/leetcode724寻找数组的中心索引.md b/animation-simulation/前缀和/leetcode724寻找数组的中心索引.md index cb7d5d6..37cd6ff 100644 --- a/animation-simulation/前缀和/leetcode724寻找数组的中心索引.md +++ b/animation-simulation/前缀和/leetcode724寻找数组的中心索引.md @@ -107,3 +107,23 @@ public: } }; ``` + +Go Code: + +```go +func pivotIndex(nums []int) int { + presum := 0 + for _, num := range nums { + presum += num + } + var leftsum int + for i, num := range nums { + // 比较左半和右半是否相同 + if presum - leftsum - num == leftsum { + return i + } + leftsum += num + } + return -1 +} +``` diff --git a/animation-simulation/前缀和/leetcode974和可被K整除的子数组.md b/animation-simulation/前缀和/leetcode974和可被K整除的子数组.md index 8a10495..4ff58c6 100644 --- a/animation-simulation/前缀和/leetcode974和可被K整除的子数组.md +++ b/animation-simulation/前缀和/leetcode974和可被K整除的子数组.md @@ -129,3 +129,21 @@ public: } }; ``` + +Go Code: + +```go +func subarraysDivByK(nums []int, k int) int { + m := make(map[int]int) + cnt := 0 + sum := 0 + m[0] = 1 + for _, num := range nums { + sum += num + key := (sum % k + k) % k + cnt += m[key] + m[key]++ + } + return cnt +} +``` diff --git a/animation-simulation/单调队列单调栈/leetcode739每日温度.md b/animation-simulation/单调队列单调栈/leetcode739每日温度.md index 6ef56d0..0ce27a7 100644 --- a/animation-simulation/单调队列单调栈/leetcode739每日温度.md +++ b/animation-simulation/单调队列单调栈/leetcode739每日温度.md @@ -58,3 +58,26 @@ class Solution { } } ``` + +GO Code: + +```go +func dailyTemperatures(temperatures []int) []int { + l := len(temperatures) + if l == 0 { + return temperatures + } + stack := []int{} + arr := make([]int, l) + for i := 0; i < l; i++ { + for len(stack) != 0 && temperatures[i] > temperatures[stack[len(stack) - 1]] { + idx := stack[len(stack) - 1] + arr[idx] = i - idx + stack = stack[: len(stack) - 1] + } + // 栈保存的是索引 + stack = append(stack, i) + } + return arr +} +``` diff --git a/animation-simulation/单调队列单调栈/剑指offer59队列的最大值.md b/animation-simulation/单调队列单调栈/剑指offer59队列的最大值.md index dd481e9..f33c7ea 100644 --- a/animation-simulation/单调队列单调栈/剑指offer59队列的最大值.md +++ b/animation-simulation/单调队列单调栈/剑指offer59队列的最大值.md @@ -89,4 +89,56 @@ class MaxQueue { } ``` +GO Code: + +```go +type MaxQueue struct { + que []int // 普通队列 + deq []int // 双端队列 + size int // que的队列长度 +} + + +func Constructor() MaxQueue { + return MaxQueue{ + que: []int{}, + deq: []int{}, + } +} + +// Is_empty 表示队列是否为空 +func (mq *MaxQueue) Is_empty() bool { + return mq.size == 0 +} + +// Max_value 取最大值值,返回我们双端队列的对头即可,因为我们双端队列是单调递减的嘛 +func (mq *MaxQueue) Max_value() int { + if mq.Is_empty() { return -1 } + return mq.deq[0] +} + +// Push_back 入队 +func (mq *MaxQueue) Push_back(value int) { + mq.que = append(mq.que, value) + // 维护单调递减队列 + for len(mq.deq) != 0 && mq.deq[len(mq.deq) - 1] < value { + mq.deq = mq.deq[:len(mq.deq) - 1] + } + mq.deq = append(mq.deq, value) + mq.size++ +} + +// Pop_front 弹出队列头元素,并且返回其值。 +func (mq *MaxQueue) Pop_front() int { + if mq.Is_empty() { return -1 } + ans := mq.que[0] + mq.que = mq.que[1:] + if mq.deq[0] == ans { + mq.deq = mq.deq[1:] + } + mq.size-- + return ans +} +``` + ### diff --git a/animation-simulation/单调队列单调栈/接雨水.md b/animation-simulation/单调队列单调栈/接雨水.md index f1c93af..69b6950 100644 --- a/animation-simulation/单调队列单调栈/接雨水.md +++ b/animation-simulation/单调队列单调栈/接雨水.md @@ -117,4 +117,35 @@ class Solution { } ``` +GO Code: + +```go +func trap(height []int) int { + stack := []int{} + water := 0 + // 最左边部分不会接雨水,左边持续升高时,stack都会弹出所有元素。 + for i := 0; i< len(height); i++ { + for len(stack) != 0 && height[i] > height[stack[len(stack) - 1]] { + popnum := stack[len(stack) - 1] + // 出现相同高度的情况(其实也可以不用处理,如果不处理,相同高度时后面的hig为0,会产生很多无效的计算) + for len(stack) != 0 && height[popnum] == height[stack[len(stack) - 1]] { + stack = stack[:len(stack) - 1] + } + if len(stack) == 0 { break } + le, ri := stack[len(stack) - 1], i + hig := min(height[ri], height[le]) - height[popnum] + wid := ri - le - 1 + water += wid * hig + } + stack = append(stack, i) + } + return water +} + +func min(a, b int) int { + if a < b { return a } + return b +} +``` + ### diff --git a/animation-simulation/单调队列单调栈/最小栈.md b/animation-simulation/单调队列单调栈/最小栈.md index c080e81..76b0fb8 100644 --- a/animation-simulation/单调队列单调栈/最小栈.md +++ b/animation-simulation/单调队列单调栈/最小栈.md @@ -73,4 +73,48 @@ class MinStack { } ``` +GO Code: + +```go +type MinStack struct { + stack []int + minStk []int +} + +/** initialize your data structure here. */ +func Constructor() MinStack { + return MinStack{ + stack: []int{}, + minStk: []int{}, + } +} + +// Push 入栈,如果插入值,当前插入值小于栈顶元素,则入栈,栈顶元素保存的则为当前栈的最小元素 +func (m *MinStack) Push(x int) { + m.stack = append(m.stack, x) + if len(m.minStk) == 0 || m.minStk[len(m.minStk) - 1] >= x { + m.minStk = append(m.minStk, x) + } +} + +// Pop 出栈,如果stack出栈等于minStk栈顶元素,则说明此时栈内的最小元素改变了。 +func (m *MinStack) Pop() { + temp := m.stack[len(m.stack) - 1] + m.stack = m.stack[: len(m.stack) - 1] + if temp == m.minStk[len(m.minStk) - 1] { + m.minStk = m.minStk[: len(m.minStk) - 1] + } +} + +// Top stack的栈顶元素 +func (m *MinStack) Top() int { + return m.stack[len(m.stack) - 1] +} + +// GetMin minStk的栈顶元素 +func (m *MinStack) GetMin() int { + return m.minStk[len(m.minStk) - 1] +} +``` + ### diff --git a/animation-simulation/单调队列单调栈/滑动窗口的最大值.md b/animation-simulation/单调队列单调栈/滑动窗口的最大值.md index 05362e1..dc98a1a 100644 --- a/animation-simulation/单调队列单调栈/滑动窗口的最大值.md +++ b/animation-simulation/单调队列单调栈/滑动窗口的最大值.md @@ -72,3 +72,37 @@ class Solution { } } ``` + +GO Code: + +```go +func maxSlidingWindow(nums []int, k int) []int { + l := len(nums) + if l == 0 { + return nums + } + + arr := []int{} + // 维护一个单调递减的双向队列 + deque := []int{} + for i := 0; i < k; i++ { + for len(deque) != 0 && deque[len(deque) - 1] < nums[i] { + deque = deque[:len(deque) - 1] + } + deque = append(deque, nums[i]) + } + + arr = append(arr, deque[0]) + for i := k; i < l; i++ { + if nums[i - k] == deque[0] { + deque = deque[1:] + } + for len(deque) != 0 && deque[len(deque) - 1] < nums[i] { + deque = deque[:len(deque) - 1] + } + deque = append(deque, nums[i]) + arr = append(arr, deque[0]) + } + return arr +} +``` diff --git a/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md b/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md index e89e1d8..fa6a044 100644 --- a/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md +++ b/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md @@ -260,3 +260,46 @@ class Solution { } } ``` + +Go Code: + +```go +func longestSubarray(nums []int, limit int) int { + maxdeq := []int{} // 递减队列 + mindeq := []int{} // 递增队列 + + length := len(nums) + left, right, maxwin := 0, 0, 0 + for right < length { + for len(maxdeq) != 0 && maxdeq[len(maxdeq) - 1] < nums[right] { + maxdeq = maxdeq[: len(maxdeq) - 1] + } + maxdeq = append(maxdeq, nums[right]) + + for len(mindeq) != 0 && mindeq[len(mindeq) - 1] > nums[right] { + mindeq = mindeq[: len(mindeq) - 1] + } + mindeq = append(mindeq, nums[right]) + + for maxdeq[0] - mindeq[0] > limit { + if maxdeq[0] == nums[left] { + maxdeq = maxdeq[1:] + } + if mindeq[0] == nums[left] { + mindeq = mindeq[1:] + } + left++ + } + maxwin = max(maxwin, right - left + 1) + right++ + } + return maxwin +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/animation-simulation/数组篇/leetcode1两数之和.md b/animation-simulation/数组篇/leetcode1两数之和.md index 2f7e75b..13689b8 100644 --- a/animation-simulation/数组篇/leetcode1两数之和.md +++ b/animation-simulation/数组篇/leetcode1两数之和.md @@ -202,3 +202,18 @@ class Solution { } } ``` + +Go Code: + +```go +func twoSum(nums []int, target int) []int { + m := make(map[int]int) + for i, num := range nums { + if v, ok := m[target - num]; ok { + return []int{v, i} + } + m[num] = i + } + return []int{} +} +``` diff --git a/animation-simulation/数组篇/leetcode219数组中重复元素2.md b/animation-simulation/数组篇/leetcode219数组中重复元素2.md index d38fe71..d40dc16 100644 --- a/animation-simulation/数组篇/leetcode219数组中重复元素2.md +++ b/animation-simulation/数组篇/leetcode219数组中重复元素2.md @@ -222,3 +222,24 @@ class Solution { } } ``` + +Go Code: + +```go +func containsNearbyDuplicate(nums []int, k int) bool { + length := len(nums) + if length == 0 { + return false + } + m := map[int]int{} + for i := 0; i < length; i++ { + if v, ok := m[nums[i]]; ok { + if i - v <= k { + return true + } + } + m[nums[i]] = i + } + return false +} +``` diff --git a/animation-simulation/数组篇/leetcode27移除元素.md b/animation-simulation/数组篇/leetcode27移除元素.md index 8875367..1afe632 100644 --- a/animation-simulation/数组篇/leetcode27移除元素.md +++ b/animation-simulation/数组篇/leetcode27移除元素.md @@ -182,3 +182,23 @@ class Solution { } } ``` + +Go Code: + +```go +func removeElement(nums []int, val int) int { + length := len(nums) + if length == 0 { + return 0 + } + i := 0 + for j := 0; j < length; j++ { + if nums[j] == val { + continue + } + nums[i] = nums[j] + i++ + } + return i +} +``` diff --git a/animation-simulation/数组篇/leetcode41缺失的第一个正数.md b/animation-simulation/数组篇/leetcode41缺失的第一个正数.md index a93de55..f7458bb 100644 --- a/animation-simulation/数组篇/leetcode41缺失的第一个正数.md +++ b/animation-simulation/数组篇/leetcode41缺失的第一个正数.md @@ -273,3 +273,26 @@ public: } }; ``` + +Go Code: + +```go +func firstMissingPositive(nums []int) int { + length := len(nums) + if length == 0 { return 1 } + for i := 0; i < length; i++ { + // 将不在正确位置的元素放在正确的位置上。 + for nums[i] > 0 && nums[i] < length + 1 && nums[i] != i + 1 && nums[i] != nums[nums[i] - 1] { + j := nums[i] - 1 + nums[i], nums[j] = nums[j], nums[i] + } + } + // 第一个不在正确位置上的元素就是结果。 + for i := 0; i < length; i++ { + if nums[i] != i + 1 { + return i + 1 + } + } + return length + 1 +} +``` diff --git a/animation-simulation/数组篇/leetcode485最大连续1的个数.md b/animation-simulation/数组篇/leetcode485最大连续1的个数.md index 66c07c2..910b52a 100644 --- a/animation-simulation/数组篇/leetcode485最大连续1的个数.md +++ b/animation-simulation/数组篇/leetcode485最大连续1的个数.md @@ -207,3 +207,27 @@ public: } }; ``` + +Go Code: + +```go +func findMaxConsecutiveOnes(nums []int) int { + cnt, maxCnt := 0, 0 + for i := 0; i < len(nums); i++ { + if nums[i] == 1 { + cnt++ + } else { + maxCnt = max(maxCnt, cnt) + cnt = 0 + } + } + return max(maxCnt, cnt) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/animation-simulation/数组篇/leetcode54螺旋矩阵.md b/animation-simulation/数组篇/leetcode54螺旋矩阵.md index 8685b9d..c67cac8 100644 --- a/animation-simulation/数组篇/leetcode54螺旋矩阵.md +++ b/animation-simulation/数组篇/leetcode54螺旋矩阵.md @@ -180,3 +180,40 @@ class Solution { } } ``` + +Go Code: + +```go +func spiralOrder(matrix [][]int) []int { + res := []int{} + left, right := 0, len(matrix[0]) - 1 + top, down := 0, len(matrix) - 1 + + for { + for i := left; i <= right; i++ { + res = append(res, matrix[top][i]) + } + top++ + if top > down { break } + + for i := top; i <= down; i++ { + res = append(res, matrix[i][right]) + } + right-- + if left > right { break } + + for i := right; i >= left; i-- { + res = append(res, matrix[down][i]) + } + down-- + if top > down { break } + + for i := down; i >= top; i-- { + res = append(res, matrix[i][left]) + } + left++ + if left > right { break } + } + return res +} +``` diff --git a/animation-simulation/数组篇/leetcode560和为K的子数组.md b/animation-simulation/数组篇/leetcode560和为K的子数组.md index 2e73caf..4bd1365 100644 --- a/animation-simulation/数组篇/leetcode560和为K的子数组.md +++ b/animation-simulation/数组篇/leetcode560和为K的子数组.md @@ -217,3 +217,22 @@ public: } }; ``` + +Go Code: + +```go +func subarraySum(nums []int, k int) int { + m := map[int]int{} + m[0] = 1 + sum := 0 + cnt := 0 + for _, num := range nums { + sum += num + if v, ok := m[sum - k]; ok { + cnt += v + } + m[sum]++ + } + return cnt +} +``` diff --git a/animation-simulation/数组篇/leetcode59螺旋矩阵2.md b/animation-simulation/数组篇/leetcode59螺旋矩阵2.md index a43f204..1b07d43 100644 --- a/animation-simulation/数组篇/leetcode59螺旋矩阵2.md +++ b/animation-simulation/数组篇/leetcode59螺旋矩阵2.md @@ -360,3 +360,47 @@ class Solution { } } ``` + +Go Code: + +```go +func generateMatrix(n int) [][]int { + res := make([][]int, n) + for i := 0; i < n; i++ { + res[i] = make([]int, n) + } + left, right := 0, n - 1 + top, buttom := 0, n - 1 + size, num := n * n, 1 + for { + for i := left; i <= right; i++ { + res[top][i] = num + num++ + } + top++ + if num > size { break } + + for i := top; i <= buttom; i++ { + res[i][right] = num + num++ + } + right-- + if num > size { break } + + for i := right; i >= left; i-- { + res[buttom][i] = num + num++ + } + buttom-- + if num > size { break } + + for i := buttom; i >= top; i-- { + res[i][left] = num + num++ + } + left++ + if num > size { break } + } + return res +} +``` diff --git a/animation-simulation/数组篇/leetcode66加一.md b/animation-simulation/数组篇/leetcode66加一.md index 204a51b..34822e1 100644 --- a/animation-simulation/数组篇/leetcode66加一.md +++ b/animation-simulation/数组篇/leetcode66加一.md @@ -122,3 +122,19 @@ class Solution { } } ``` + +Go Code: + +```go +func plusOne(digits []int) []int { + l := len(digits) + for i := l - 1; i >= 0; i-- { + digits[i] = (digits[i] + 1) % 10 + if digits[i] != 0 { + return digits + } + } + digits = append([]int{1}, digits...) + return digits +} +``` diff --git a/animation-simulation/数组篇/leetcode75颜色分类.md b/animation-simulation/数组篇/leetcode75颜色分类.md index 4f69ce5..7fc2400 100644 --- a/animation-simulation/数组篇/leetcode75颜色分类.md +++ b/animation-simulation/数组篇/leetcode75颜色分类.md @@ -149,6 +149,30 @@ class Solution { } ``` +Go Code: + +```go +func sortColors(nums []int) { + length := len(nums) + left, right := 0, length - 1 + i := left + for i <= right { + if nums[i] == 2 { + // 把2换到最后 + nums[i], nums[right] = nums[right], nums[i] + right-- + } else if nums[i] == 0 { + // 把0换到最前面 + nums[i], nums[left] = nums[left], nums[i] + i++ + left++ + } else { + i++ + } + } +} +``` + 另外我们看这段代码,有什么问题呢?那就是我们即使完全符合时,仍会交换元素,这样会大大降低我们的效率。 例如:[0,0,0,1,1,1,2,2,2] @@ -286,3 +310,27 @@ class Solution { } } ``` + +Go Code: + +```go +func sortColors(nums []int) { + length := len(nums) + left, right := 0, length - 1 + for i := 0; i <= right; i++ { + if nums[i] == 0 { + // 为0时,和头交换 + nums[i], nums[left] = nums[left], nums[i] + left++ + } else if nums[i] == 2 { + // 为2时,和尾交换 + nums[i], nums[right] = nums[right], nums[i] + right-- + // 不为1时,需要把i减回去 + if nums[i] != 1 { + i-- + } + } + } +} +``` diff --git a/animation-simulation/数组篇/剑指offer3数组中重复的数.md b/animation-simulation/数组篇/剑指offer3数组中重复的数.md index c0f077b..0bffd1b 100644 --- a/animation-simulation/数组篇/剑指offer3数组中重复的数.md +++ b/animation-simulation/数组篇/剑指offer3数组中重复的数.md @@ -174,3 +174,24 @@ class Solution { } } ``` + +Go Code: + +```go +func findRepeatNumber(nums []int) int { + l := len(nums) + if l == 0 { + return -1 + } + for i := 0; i < l; i++ { + // 将nums[i]换到i的位置。 + for nums[i] != i { + if nums[i] == nums[nums[i]] { + return nums[i] + } + nums[i], nums[nums[i]] = nums[nums[i]], nums[i] + } + } + return -1 +} +``` diff --git a/animation-simulation/数组篇/长度最小的子数组.md b/animation-simulation/数组篇/长度最小的子数组.md index 2128917..f59ad75 100644 --- a/animation-simulation/数组篇/长度最小的子数组.md +++ b/animation-simulation/数组篇/长度最小的子数组.md @@ -119,3 +119,33 @@ class Solution { } } ``` + +Go Code: + +```go +func minSubArrayLen(target int, nums []int) int { + length := len(nums) + winLen := length + 1 + i := 0 + sum := 0 + for j := 0; j < length; j++ { + sum += nums[j] + for sum >= target { + winLen = min(winLen, j - i + 1) + sum -= nums[i] + i++ + } + } + if winLen == length + 1 { + return 0 + } + return winLen +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` diff --git a/animation-simulation/求和问题/三数之和.md b/animation-simulation/求和问题/三数之和.md index 991b27e..24dce28 100644 --- a/animation-simulation/求和问题/三数之和.md +++ b/animation-simulation/求和问题/三数之和.md @@ -162,3 +162,50 @@ class Solution { } } ``` + +Go Code: + +```go +func threeSum(nums []int) [][]int { + res := [][]int{} + length := len(nums) + if length < 3 { + return res + } + + sort.Ints(nums) + for i := 0; i < length - 2; i++ { + // 去重 + if i != 0 && nums[i] == nums[i - 1] { + continue + } + l, r := i + 1, length - 1 + for l < r { + /* + // 下面两个for循环的去重也可以用下面的代码替换 + if l != i + 1 && nums[l] == nums[l - 1] { + l++ + continue + } + */ + if nums[i] + nums[l] + nums[r] == 0 { + res = append(res, []int{nums[i], nums[l], nums[r]}) + for l < r && nums[l] == nums[l + 1] { + l++ + } + for l < r && nums[r] == nums[r - 1] { + r-- + } + l++ + r-- + } else if nums[i] + nums[l] + nums[r] < 0 { + l++ + } else { + r-- + } + + } + } + return res +} +``` diff --git a/animation-simulation/求和问题/两数之和.md b/animation-simulation/求和问题/两数之和.md index f853fa3..1e995ec 100644 --- a/animation-simulation/求和问题/两数之和.md +++ b/animation-simulation/求和问题/两数之和.md @@ -54,6 +54,21 @@ class Solution { } ``` +Go Code: + +```go +func twoSum(nums []int, target int) []int { + m := make(map[int]int) + for i, num := range nums { + if v, ok := m[target - num]; ok { + return []int{v, i} + } + m[num] = i + } + return []int{} +} +``` + ### 双指针(暴力)法 #### 解析 diff --git a/animation-simulation/求和问题/四数之和.md b/animation-simulation/求和问题/四数之和.md index ac0c8d5..05524a4 100644 --- a/animation-simulation/求和问题/四数之和.md +++ b/animation-simulation/求和问题/四数之和.md @@ -95,3 +95,57 @@ class Solution { } } ``` + +Go Code: + +```go +func fourSum(nums []int, target int) [][]int { + res := [][]int{} + length := len(nums) + if length < 4 { + return res + } + + sort.Ints(nums) + for i := 0; i < length - 3; i++ { + // 去重 + if i != 0 && nums[i] == nums[i - 1] { + continue + } + for j := i + 1; j < length - 2; j++ { + // 去重 + if j != i + 1 && nums[j] == nums[j - 1] { + continue + } + l, r := j + 1, length - 1 + for l < r { + /* + // 下面两个for循环的去重也可以用下面的代码替换 + if l != i + 1 && nums[l] == nums[l - 1] { + l++ + continue + } + */ + sum := nums[i] + nums[j] + nums[l] + nums[r] + if sum == target { + res = append(res, []int{nums[i], nums[j], nums[l], nums[r]}) + for l < r && nums[l] == nums[l + 1] { + l++ + } + for l < r && nums[r] == nums[r - 1] { + r-- + } + l++ + r-- + } else if sum < target { + l++ + } else { + r-- + } + + } + } + } + return res +} +``` diff --git a/animation-simulation/求次数问题/只出现一次的数.md b/animation-simulation/求次数问题/只出现一次的数.md index c5f563e..d8a792e 100644 --- a/animation-simulation/求次数问题/只出现一次的数.md +++ b/animation-simulation/求次数问题/只出现一次的数.md @@ -131,6 +131,26 @@ class Solution: return y ``` +Go Code: + +```go +func singleNumber(nums []int) int { + if len(nums) == 1 { + return nums[0] + } + m := map[int]int{} + for _, x := range nums { + m[x]++ + } + for k, v := range m { + if v == 1 { + return k + } + } + return 0 +} +``` + ### 排序搜索法 #### 解析 @@ -208,6 +228,25 @@ class Solution: return nums[len(nums) - 1] ``` +Go Code: + +```go +func singleNumber(nums []int) int { + if len(nums) == 1 { + return nums[0] + } + sort.Ints(nums) + for i := 1; i < len(nums) - 1; i+=2 { + if nums[i] == nums[i - 1] { + continue + } else { + return nums[i - 1] + } + } + return nums[len(nums) - 1] +} +``` + ### HashSet #### 解析 @@ -565,4 +604,17 @@ class Solution: return reduce(lambda num, x: num ^ x, nums, 0) ``` +Go Code: + +```go +func singleNumber(nums []int) int { + res := 0 + for _, x := range nums { + res ^= x + } + return res + +} +``` + 本题一共介绍了 6 种解题方法,肯定还有别的方法,欢迎大家讨论。大家可以在做题的时候一题多解。这样能大大提高自己解题能力。下面我们来看一下这些方法如何应用到其他题目上。 diff --git a/animation-simulation/求次数问题/只出现一次的数2.md b/animation-simulation/求次数问题/只出现一次的数2.md index 755a9e7..7debb54 100644 --- a/animation-simulation/求次数问题/只出现一次的数2.md +++ b/animation-simulation/求次数问题/只出现一次的数2.md @@ -216,6 +216,27 @@ class Solution: return res ``` +Go Code: + +```go +func singleNumber(nums []int) int { + res := 0 + // Go语言中,int占32位以上 + for i := 0; i < 64; i++ { + cnt := 0 + for j := 0; j < len(nums); j++ { + if (nums[j] >> i & 1) == 1 { + cnt++ + } + } + if cnt % 3 != 0{ + res = res | 1 << i + } + } + return res +} +``` + 我们来解析一下我们的代码: > **<<** 左移运算符:运算数的各二进位全部左移若干位,由 **<<** 右边的数字指定了移动的位数,高位丢弃,低位补 0。 diff --git a/animation-simulation/求次数问题/只出现一次的数3.md b/animation-simulation/求次数问题/只出现一次的数3.md index af9e1de..700c184 100644 --- a/animation-simulation/求次数问题/只出现一次的数3.md +++ b/animation-simulation/求次数问题/只出现一次的数3.md @@ -263,3 +263,26 @@ class Solution: arr[1] ^= y return arr ``` + +Go Code: + +```go +func singleNumber(nums []int) []int { + temp := 0 + for _, x := range nums { + temp ^= x + } + // 保留最后那个1,为了区分两个数 + group := temp & (^temp + 1) + + res := make([]int, 2) + for _, x := range nums { + if group & x == 0{ + res[0] ^= x + } else { + res[1] ^= x + } + } + return res +} +``` diff --git a/animation-simulation/链表篇/234. 回文链表.md b/animation-simulation/链表篇/234. 回文链表.md index 134f042..2e90e76 100644 --- a/animation-simulation/链表篇/234. 回文链表.md +++ b/animation-simulation/链表篇/234. 回文链表.md @@ -173,6 +173,30 @@ class Solution { } ``` +Go Code: + +```go +func isPalindrome(head *ListNode) bool { + // 将节点中的值按顺序放在arr中。 + arr := []int{} + node := head + for node != nil { + arr = append(arr, node.Val) + node = node.Next + } + // 双指针判断是否为回文 + l, r := 0, len(arr) - 1 + for l < r { + if arr[l] != arr[r] { + return false + } + l++ + r-- + } + return true +} +``` + 这个方法可以直接通过,但是这个方法需要辅助数组,那我们还有其他更好的方法吗? **双指针翻转链表法** @@ -457,3 +481,52 @@ class Solution { } } ``` + +Go Code: + +```go +func isPalindrome(head *ListNode) bool { + if head == nil || head.Next == nil { + return true + } + + midNode := searchMidNode(head) + backHalf := reverse(midNode.Next) + + // 判断左右两边是否一样(回文) + p1, p2 := head, backHalf + for p2 != nil { + if p1.Val != p2.Val { + midNode.Next = reverse(backHalf) + return false + } + p1 = p1.Next + p2 = p2.Next + } + // 不破坏原来的数据 + midNode.Next = reverse(backHalf) + return true +} + +// searchMidNode 求中间的节点 +func searchMidNode(head *ListNode) *ListNode { + fast, slow := head, head + for fast.Next != nil && fast.Next.Next != nil { + fast = fast.Next.Next + slow = slow.Next + } + return slow +} + +// reverse 反转链表 +func reverse(node *ListNode) *ListNode { + var pre *ListNode + for node != nil { + nxt := node.Next + node.Next = pre + pre = node + node = nxt + } + return pre +} +``` diff --git a/animation-simulation/链表篇/leetcode141环形链表.md b/animation-simulation/链表篇/leetcode141环形链表.md index 63127e1..e8d48f9 100644 --- a/animation-simulation/链表篇/leetcode141环形链表.md +++ b/animation-simulation/链表篇/leetcode141环形链表.md @@ -124,3 +124,20 @@ class Solution { } } ``` + +Go Code: + +```go +func hasCycle(head *ListNode) bool { + if head == nil { return false } + s, f := head, head + for f != nil && f.Next != nil { + s = s.Next + f = f.Next.Next + if s == f { + return true + } + } + return false +} +``` diff --git a/animation-simulation/链表篇/leetcode142环形链表2.md b/animation-simulation/链表篇/leetcode142环形链表2.md index 7884457..4b00fea 100644 --- a/animation-simulation/链表篇/leetcode142环形链表2.md +++ b/animation-simulation/链表篇/leetcode142环形链表2.md @@ -297,3 +297,27 @@ class Solution { } } ``` + +Go Code: + +```go +func detectCycle(head *ListNode) *ListNode { + if head == nil { return nil } + s, f := head, head + for f != nil && f.Next != nil { + s = s.Next + f = f.Next.Next + // 快慢指针相遇 + if f == s { + // 快指针从头开始一步一步走,也可以用一个新的指针 + f = head + for f != s { + f = f.Next + s = s.Next + } + return f + } + } + return nil +} +``` diff --git a/animation-simulation/链表篇/leetcode147对链表进行插入排序.md b/animation-simulation/链表篇/leetcode147对链表进行插入排序.md index c4d1d4e..644be2b 100644 --- a/animation-simulation/链表篇/leetcode147对链表进行插入排序.md +++ b/animation-simulation/链表篇/leetcode147对链表进行插入排序.md @@ -257,3 +257,34 @@ class Solution { } } ``` + +Go Code: + +```go +func insertionSortList(head *ListNode) *ListNode { + if head == nil || head.Next == nil { return head } + root := &ListNode{ + Next: head, + } + cur, nxt := head, head.Next + for nxt != nil { + // 有序的不需要换位置 + if cur.Val <= nxt.Val { + cur = cur.Next + nxt = nxt.Next + continue + } + temp := root + for temp.Next.Val <= nxt.Val { + temp = temp.Next + } + // 此时找到合适的位置 + cur.Next = nxt.Next + nxt.Next = temp.Next + temp.Next = nxt + // 继续向下 + nxt = cur.Next + } + return root.Next +} +``` diff --git a/animation-simulation/链表篇/leetcode206反转链表.md b/animation-simulation/链表篇/leetcode206反转链表.md index 7e27978..0ab7915 100644 --- a/animation-simulation/链表篇/leetcode206反转链表.md +++ b/animation-simulation/链表篇/leetcode206反转链表.md @@ -164,6 +164,27 @@ class Solution { } ``` +Go Code: + +```go +func reverseList(head *ListNode) *ListNode { + if head == nil || head.Next == nil { return head } + cur := head + var pre *ListNode + for cur != nil { + nxt := cur.Next + cur.Next = pre + pre = cur + cur = nxt + if nxt == nil { + return pre + } + nxt = nxt.Next + } + return pre +} +``` + 上面的迭代写法是不是搞懂啦,现在还有一种递归写法,不是特别容易理解,刚开始刷题的同学,可以只看迭代解法。 **题目代码** diff --git a/animation-simulation/链表篇/leetcode328奇偶链表.md b/animation-simulation/链表篇/leetcode328奇偶链表.md index d43afac..0b1edc7 100644 --- a/animation-simulation/链表篇/leetcode328奇偶链表.md +++ b/animation-simulation/链表篇/leetcode328奇偶链表.md @@ -155,3 +155,23 @@ class Solution { } } ``` + +Go Code: + +```go +func oddEvenList(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + odd, even := head, head.Next + evenHead := even + for odd.Next != nil && even.Next != nil { + odd.Next = even.Next + odd = odd.Next + even.Next = odd.Next + even = even.Next + } + odd.Next = evenHead + return head +} +``` diff --git a/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md b/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md index 1880959..56d8354 100644 --- a/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md +++ b/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md @@ -194,3 +194,30 @@ class Solution { } } ``` + +Go Code: + +```go +func deleteDuplicates(head *ListNode) *ListNode { + // 新建一个头结点,他的下一个节点才是开始 + root := &ListNode{ + Next: head, + } + pre, cur := root, head + for cur != nil && cur.Next != nil { + if cur.Val == cur.Next.Val { + // 相等的话,cur就一直向后移动 + for cur != nil && cur.Next != nil && cur.Val == cur.Next.Val { + cur = cur.Next + } + // 循环后移动到了最后一个相同的节点。 + cur = cur.Next + pre.Next = cur + } else { + cur = cur.Next + pre = pre.Next + } + } + return root.Next +} +``` diff --git a/animation-simulation/链表篇/leetcode86分隔链表.md b/animation-simulation/链表篇/leetcode86分隔链表.md index da4890c..e90893a 100644 --- a/animation-simulation/链表篇/leetcode86分隔链表.md +++ b/animation-simulation/链表篇/leetcode86分隔链表.md @@ -187,3 +187,29 @@ class Solution { } } ``` + +Go Code: + +```go +func partition(head *ListNode, x int) *ListNode { + big, small := &ListNode{}, &ListNode{} + headBig, headSmall := big, small + temp := head + for temp != nil { + // 分开存 + if temp.Val < x { + small.Next = temp + small = small.Next + } else { + big.Next = temp + big = big.Next + } + temp = temp.Next + } + // 最后一个节点指向nil + big.Next = nil + // 存小数的链表和存大数的连起来 + small.Next = headBig.Next + return headSmall.Next +} +``` diff --git a/animation-simulation/链表篇/leetcode92反转链表2.md b/animation-simulation/链表篇/leetcode92反转链表2.md index f07f220..22eb6dd 100644 --- a/animation-simulation/链表篇/leetcode92反转链表2.md +++ b/animation-simulation/链表篇/leetcode92反转链表2.md @@ -263,3 +263,46 @@ class Solution { } } ``` + +GoCode: + +```go +func reverseBetween(head *ListNode, left int, right int) *ListNode { + root := &ListNode{ + Next: head, + } + temp := root + i := 0 + // left的前一个节点 + for ; i < left - 1; i++ { + temp = temp.Next + } + leftNode := temp + // right的后一个节点 + for ; i < right; i++ { + temp = temp.Next + } + rightNode := temp.Next + // 切断链表 + temp.Next = nil + newhead := leftNode.Next + leftNode.Next = nil + + // 反转后将3段链表接上。 + leftNode.Next = reverse(newhead) + newhead.Next = rightNode + return root.Next +} + +func reverse(head *ListNode) *ListNode { + var pre *ListNode + cur := head + for cur != nil { + temp := cur + cur = cur.Next + temp.Next = pre + pre = temp + } + return pre +} +``` diff --git a/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md b/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md index a58d2fb..007270e 100644 --- a/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md +++ b/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md @@ -146,3 +146,29 @@ class Solution { } } ``` + +Go Code: + +```go +func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode { + root := &ListNode{} + node := root + for l1 != nil && l2 != nil { + if l1.Val < l2.Val { + node.Next = l1 + l1 = l1.Next + } else { + node.Next = l2 + l2 = l2.Next + } + node = node.Next + } + // node接上l1或l2剩下的节点 + if l1 != nil { + node.Next = l1 + } else { + node.Next = l2 + } + return root.Next +} +``` diff --git a/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md b/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md index e95eb95..823f17e 100644 --- a/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md +++ b/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md @@ -265,6 +265,28 @@ class Solution { } ``` +Go Code: + +```go +func getIntersectionNode(headA, headB *ListNode) *ListNode { + tempA, tempB := headA, headB + for tempA != tempB { + // 如果不为空就指针下移,为空就跳到另一链表的头部 + if tempA == nil { + tempA = headB + } else { + tempA = tempA.Next + } + if tempB == nil { + tempB = headA + } else { + tempB = tempB.Next + } + } + return tempA +} +``` + 好啦,链表的题目就结束啦,希望大家能有所收获,下周就要更新新的题型啦,继续坚持,肯定会有收获的。
diff --git a/animation-simulation/链表篇/剑指offer22倒数第k个节点.md b/animation-simulation/链表篇/剑指offer22倒数第k个节点.md index 5a358c5..037cd0e 100644 --- a/animation-simulation/链表篇/剑指offer22倒数第k个节点.md +++ b/animation-simulation/链表篇/剑指offer22倒数第k个节点.md @@ -163,3 +163,21 @@ class Solution { } } ``` + +Go Code: + +```go +func getKthFromEnd(head *ListNode, k int) *ListNode { + if head == nil { return head } + pro, after := head, head + //先移动绿指针到指定位置 + for i := 0; i < k - 1; i++ { + pro = pro.Next + } + for pro.Next != nil { + pro = pro.Next + after = after.Next + } + return after +} +``` diff --git a/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md b/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md index 9056f0d..72693e7 100644 --- a/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md +++ b/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md @@ -135,3 +135,17 @@ class Solution { } } ``` + +Go Code: + +```go +func middleNode(head *ListNode) *ListNode { + // 快慢指针 + fast, slow := head, head + for fast != nil && fast.Next != nil { + fast = fast.Next.Next + slow = slow.Next + } + return slow +} +``` diff --git a/animation-simulation/链表篇/面试题 02.05. 链表求和.md b/animation-simulation/链表篇/面试题 02.05. 链表求和.md index 1f09fa4..fcdb8c5 100644 --- a/animation-simulation/链表篇/面试题 02.05. 链表求和.md +++ b/animation-simulation/链表篇/面试题 02.05. 链表求和.md @@ -267,3 +267,40 @@ class Solution { } } ``` + +Go Code: + +```go +func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { + root := &ListNode{} + temp := root + // 用来保存进位值,初始化为0 + mod := 0 + for (l1 != nil || l2 != nil) { + l1num := 0 + if l1 != nil { l1num = l1.Val } + l2num := 0 + if l2 != nil { l2num = l2.Val } + // 将链表的值和进位值相加,得到为返回链表的值 + sum := l1num + l2num + mod + // 更新进位值,例18/10=1,9/10=0 + mod = sum / 10 + // 新节点保存的值,18%8=2,则添加2 + sum = sum % 10 + newNode := &ListNode{ + Val: sum, + } + temp.Next = newNode + temp = temp.Next + if l1 != nil { l1 = l1.Next } + if l2 != nil { l2 = l2.Next } + } + if mod != 0 { + newNode := &ListNode{ + Val: mod, + } + temp.Next = newNode + } + return root.Next +} +```