📋这是一个记录自己偶尔算法练习的代码仓库,有时间练一练,开发一下大脑
本项目用于整理和记录我的 LeetCode 刷题代码与思路,按照数据结构与算法类型分类展示。
点击表格中的题目可以直接跳转到该题的详细代码实现。
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 两数之和 | 哈希表 | 1. 两数之和 - 力扣(LeetCode) | 🟢 Easy |
| 2 | 最长公共前缀 | 动态规划 | 14. 最长公共前缀 - 力扣(LeetCode) | 🟢 Easy |
| 3 | 三数之和 | 动态规划 | LCR 007. 三数之和 - 力扣(LeetCode) | 🟢 Easy |
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 反转链表 | 链表 | 206. 反转链表 - 力扣(LeetCode) | 🟢 Easy |
| 2 | 两两交换链表中的节点 | 链表 | 24. 两两交换链表中的节点 - 力扣(LeetCode) | 🟢 Easy |
| 3 | 环形链表 | 链表 | 141. 环形链表 - 力扣(LeetCode) | 🟢 Easy |
| 4 | 环形链表-找入环点 | 链表 | 142. 环形链表 II - 力扣(LeetCode)- 找入环点 | 🟢 Easy |
| 5 | K个一组翻转链表 | 链表 | 25. K 个一组翻转链表 - 力扣(LeetCode) | 🟢 Easy |
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 有效的括号 | 栈 | 20. 有效的括号 - 力扣(LeetCode) | 🟢 Easy |
| 2 | 用栈实现队列 | 栈 | 232. 用栈实现队列 - 力扣(LeetCode) | 🟢 Easy |
| 3 | 用队列实现栈 | 栈 | 225. 用队列实现栈 - 力扣(LeetCode) | 🟢 Easy |
| 4 | 股票价格跨度 | 单调栈 | 901. 股票价格跨度 - 力扣(LeetCode) | 🟢 Easy |
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 数据流中的第K大元素 | 堆 | 703. 数据流中的第 K 大元素 - 力扣(LeetCode) | 🟢 Easy |
| 2 | 滑动窗口最大值 | 队列 | 239. 滑动窗口最大值 - 力扣(LeetCode) | 🟢 Easy |
| 3 | 早餐组合 | 队列 | LCP 18. 早餐组合 - 力扣(LeetCode) | 🟢 Easy |
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 相同的树 | 二叉树 | 100. 相同的树 - 力扣(LeetCode) | 🟢 Easy |
| 2 | 验证二叉搜索树 | 二叉树 | 98. 验证二叉搜索树 - 力扣(LeetCode) | 🟢 Easy |
| 3 | 二叉树的最近公共祖先 | 二叉树 | 236. 二叉树的最近公共祖先 - 力扣(LeetCode) | 🟢 Easy |
| 4 | 二叉树的最近公共祖先 | 二叉树 | 235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode) | 🟢 Easy |
| 5 | 二叉树的中序遍历 | 二叉树,递归 | 94. 二叉树的中序遍历 - 力扣(LeetCode) | 🟢 Easy |
| 6 | 对称二叉树 | 二叉树,递归 | 101. 对称二叉树 - 力扣(LeetCode) | 🟢 Easy |
| 7 | 二叉树的层序遍历 | 二叉树,队列 | 102. 二叉树的层序遍历 - 力扣(LeetCode) | 🟢 Easy |
| 8 | 二叉树的最小深度 | 二叉树,bfs,dfs | 111. 二叉树的最小深度 - 力扣(LeetCode) | 🟢 Easy |
| 9 | 二叉树的最大深度 | 二叉树,bfs,dfs | 104. 二叉树的最大深度 - 力扣(LeetCode) | 🟢 Easy |
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 有效的字母异位词 | 哈希表 | 242. 有效的字母异位词 - 力扣(LeetCode) | 🟢 Easy |
| 2 | 多数元素 | 哈希表 | 169. 多数元素 - 力扣(LeetCode) | 🟢 Easy |
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | x的n次方 | 分治 | 50. Pow(x, n) - 力扣(LeetCode) | 🟢 Easy |
| 2 | 括号生成 | 递归 | 22. 括号生成 - 力扣(LeetCode) | 🟢 Easy |
在进行问题求解的时候,只做当前最优的选择。适用场景:问题能够被分为子问题来求解,并且子问题的最优解能够递推到最终问题的最优解。
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 买卖股票的最佳时机 II | 贪心 | 122. 买卖股票的最佳时机 II - 力扣(LeetCode) | 🟢 Easy |
| # | 题目 | 类型 | LeetCode | 难度 |
|---|---|---|---|---|
| 1 | 十进制整数的反码 | 抑或运算 | 1009. 十进制整数的反码 - 力扣(LeetCode) | 🟢 Easy |
func twoSum(nums []int, target int) []int {
m := map[int]int{}
for index1, v1 := range nums {
if index2, ok := m[target - v1]; !ok {
m[v1] = index1
} else {
return []int{index2, index1}
}
}
return nil
}func longestCommonPrefix(strs []string) string {
u := []rune{}
flag := true
for index, c := range strs[0] {
for i := 1; i < len(strs) && flag == true; i++ {
if index < len(strs[i]) && rune(strs[i][index]) == c {
flag = true
} else {
flag = false
break
}
}
if flag == true {
u = append(u, c)
}
}
return string(u)
}
func threeSum(nums []int) [][]int {
sort.Ints(nums)
var res [][]int
n := len(nums)
for i := 0; i < n-2; i++ {
// 避免生成相同的target,去重
if i > 0 && nums[i] == nums[i-1] {
continue
}
target := -nums[i]
tmp := make(map[int]bool)
for j := i + 1; j < n; j++ {
a := target - nums[j]
if tmp[a] { // a与map中的值可以相同
res = append(res, []int{nums[i], a, nums[j]})
for j+1 < n && nums[j] == nums[j+1] {
j++
}
}
tmp[nums[j]] = true
}
}
return res
}/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
prev := (*ListNode)(nil)
cur := head
for cur != nil {
head = head.Next
cur.Next = prev
prev = cur
cur = head
}
return prev
}/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func swapPairs(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
prevHead := &ListNode{0, head}
cur, swapNode := head, head.Next
rt := swapNode
for {
prevHead.Next = swapNode
cur.Next = swapNode.Next
swapNode.Next = cur
prevHead = cur
if cur.Next != nil && cur.Next.Next != nil {
cur = cur.Next
swapNode = cur.Next
}else {
break
}
}
return rt
}/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func hasCycle(head *ListNode) bool {
// fast, slow := head, head
// for slow != nil && fast != nil && fast.Next != nil {
// slow = slow.Next
// fast = fast.Next.Next
// if slow == fast {
// return true
// }
// }
// return false
m := map[*ListNode]struct{}{}
cur := head
for cur != nil {
if _, ok := m[cur]; ok {
return true
}else {
m[cur] = struct{}{}
}
cur = cur.Next
}
return false
}/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func detectCycle(head *ListNode) *ListNode {
// m := map[*ListNode]struct{}{}
// for head != nil {
// if _, ok := m[head]; ok {
// return head
// }
// m[head] = struct{}{}
// head = head.Next
// }
// return nil
fast, slow := head, head
for fast != nil && fast.Next != nil{
slow = slow.Next
fast = fast.Next.Next
if slow == fast {
fast = head
for slow != fast {
fast = fast.Next
slow = slow.Next
}
return slow
}
}
return nil
}/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseKGroup(head *ListNode, k int) *ListNode {
if head == nil || head.Next == nil || k == 1 {
return head
}
dummy := &ListNode{0, head}
prevGroup := dummy
for head != nil {
curr := head
count := 0
for curr != nil && count < k {
count++
curr = curr.Next
}
if count < k {
break
}
curr = head
var prev *ListNode
for i := 0; i < k; i++ {
next := curr.Next
curr.Next = prev
prev = curr
curr = next
}
prevGroup.Next = prev
head.Next = curr
prevGroup = head
head = curr
}
return dummy.Next
}func isValid(s string) bool {
stack := []rune{}
for _, ch := range s{
switch ch {
case '(', '{', '[':
stack = append(stack, ch)
case ')', '}', ']':
if len(stack) > 0 {
if (ch == ')' && stack[len(stack)-1] == '(') ||
(ch == '}' && stack[len(stack)-1] == '{') ||
(ch == ']' && stack[len(stack)-1] == '[') {
stack = stack[:len(stack)-1]
}else {
return false
}
}else {
return false
}
}
}
return len(stack) == 0
}type MyQueue struct {
stack1 []int
stack2 []int
}
func Constructor() MyQueue {
return MyQueue{}
}
func (this *MyQueue) Push(x int) {
for len(this.stack2) > 0 {
this.stack1 = append(this.stack1, this.stack2[len(this.stack2)-1])
this.stack2 = this.stack2[:len(this.stack2)-1]
}
this.stack1 = append(this.stack1, x)
}
func (this *MyQueue) Pop() int {
if len(this.stack2) > 0 {
res := this.stack2[len(this.stack2)-1]
this.stack2 = this.stack2[:len(this.stack2)-1]
return res
}
for len(this.stack1) > 0 {
this.stack2 = append(this.stack2, this.stack1[len(this.stack1)-1])
this.stack1 = this.stack1[:len(this.stack1)-1]
}
res := this.stack2[len(this.stack2)-1]
this.stack2 = this.stack2[:len(this.stack2)-1]
return res
}
func (this *MyQueue) Peek() int {
if len(this.stack2) > 0 {
return this.stack2[len(this.stack2)-1]
}
for len(this.stack1) > 0 {
this.stack2 = append(this.stack2, this.stack1[len(this.stack1)-1])
this.stack1 = this.stack1[:len(this.stack1)-1]
}
return this.stack2[len(this.stack2)-1]
}
func (this *MyQueue) Empty() bool {
return len(this.stack1) == 0 && len(this.stack2) == 0
}
/**
* Your MyQueue object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* param_2 := obj.Pop();
* param_3 := obj.Peek();
* param_4 := obj.Empty();
*/type MyStack struct {
queue1 []int
queue2 []int
}
func Constructor() MyStack {
return MyStack{}
}
func (this *MyStack) Push(x int) {
if len(this.queue2) > 0 {
this.queue2 = append(this.queue2, x)
return
}
this.queue1 = append(this.queue1, x)
}
func (this *MyStack) Pop() int {
res := 0
if len(this.queue1) > 0 {
for len(this.queue1) > 1 {
this.queue2 = append(this.queue2, this.queue1[0])
this.queue1 = this.queue1[1:]
}
res = this.queue1[0]
this.queue1 = this.queue1[0:0]
} else {
for len(this.queue2) > 1 {
this.queue1 = append(this.queue1, this.queue2[0])
this.queue2 = this.queue2[1:]
}
res = this.queue2[0]
this.queue2 = this.queue2[0:0]
}
return res
}
func (this *MyStack) Top() int {
res := 0
if len(this.queue1) > 0 {
for len(this.queue1) > 1 {
this.queue2 = append(this.queue2, this.queue1[0])
this.queue1 = this.queue1[1:]
}
res = this.queue1[0]
this.queue1 = this.queue1[0:0]
this.queue2 = append(this.queue2, res)
} else {
for len(this.queue2) > 1 {
this.queue1 = append(this.queue1, this.queue2[0])
this.queue2 = this.queue2[1:]
}
res = this.queue2[0]
this.queue2 = this.queue2[0:0]
this.queue1 = append(this.queue1, res)
}
return res
}
func (this *MyStack) Empty() bool {
return len(this.queue1) == 0 && len(this.queue2) == 0
}
/**
* Your MyStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* param_2 := obj.Pop();
* param_3 := obj.Top();
* param_4 := obj.Empty();
*/type KthLargest struct {
u sort.IntSlice
k int
}
func Constructor(k int, nums []int) KthLargest {
kl := KthLargest{
u: sort.IntSlice(nums),
k: k,
}
sort.Sort(sort.Reverse(kl.u))
return kl
}
func (this *KthLargest) Add(val int) int {
if len(this.u) >= this.k && this.u[this.k-1] >= val {
return this.u[this.k-1]
}
this.u = append(this.u, val)
sort.Sort(sort.Reverse(this.u))
this.u = this.u[:this.k]
return this.u[this.k-1]
}
/**
* Your KthLargest object will be instantiated and called as such:
* obj := Constructor(k, nums);
* param_1 := obj.Add(val);
*/func maxSlidingWindow(nums []int, k int) []int {
if len(nums) == 0 || k <= 0 || k > len(nums) {
return []int{}
}
if k == 1 {
return nums
}
// 使用双端队列存储索引
deque := make([]int, 0, k)
// 预分配结果切片容量
res := make([]int, 0, len(nums)-k+1)
for i := 0; i < len(nums); i++ {
// 移除窗口外的索引
if len(deque) > 0 && deque[0] <= i-k {
deque = deque[1:]
}
// 移除队列尾部小于当前元素的索引,保持单调递减
for len(deque) > 0 && nums[deque[len(deque)-1]] < nums[i] {
deque = deque[:len(deque)-1]
}
// 添加当前索引
deque = append(deque, i)
// 窗口形成后记录最大值
if i >= k-1 {
res = append(res, nums[deque[0]])
}
}
return res
}func breakfastNumber(staple []int, drinks []int, x int) int {
num := 0
sort.Ints(staple)
sort.Ints(drinks)
for _, s := range staple {
target := x - s
low := 0
high := len(drinks)-1
for low <= high {
mid := (low + high) / 2
if drinks[mid] > target {
high = mid - 1
}else {
low = mid + 1
}
}
num += low
}
return num % 1000000007
}/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isSameTree(p *TreeNode, q *TreeNode) bool {
if p == nil && q == nil{return true}
if (p == nil && q != nil) || (p != nil && q == nil) || p.Val != q.Val {return false}
if p.Val == q.Val {
return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}
return false
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isValidBST(root *TreeNode) bool {
prev := new(int) // 分配内存
*prev = math.MinInt64 // 初始化为负无穷哨兵
return inorder(root, prev)
}
func inorder(node *TreeNode, prev *int) bool {
if node == nil {
return true
}
// 先递归左子树
if !inorder(node.Left, prev) {
return false
}
// 访问当前节点:检查递增性
if node.Val <= *prev {
return false
}
*prev = node.Val // 更新前驱
// 后递归右子树
if !inorder(node.Right, prev) {
return false
}
return true
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root == nil || root == p || root == q {return root}
left := lowestCommonAncestor(root.Left, p, q)
right := lowestCommonAncestor(root.Right, p, q)
if left != nil && right != nil{
return root
}
if right == nil{
return left
}
return right
}
func isAnagram(s string, t string) bool {
if len(s) != len(t) {return false}
u := map[rune]int{}
for i := 0; i < len(s); i++ {
if _, ok := u[rune(s[i])]; ok {
u[rune(s[i])]++
} else {
u[rune(s[i])] = 1
}
if _, ok := u[rune(t[i])]; ok {
u[rune(t[i])]--
} else {
u[rune(t[i])] = -1
}
}
for _, v := range u {
if v != 0 {return false}
}
return true
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
// 递归终止条件
if root == nil {return nil}
// 如果都在右子树
if p.Val > root.Val && q.Val > root.Val {
return lowestCommonAncestor(root.Right, p, q)
}
// 如果都在左子树
if p.Val < root.Val && q.Val < root.Val {
return lowestCommonAncestor(root.Left, p, q)
}
return root
}
type StockSpanner struct {
stack []pair // 单调栈,栈底价格至栈顶依此增大
}
type pair struct {
price int
span int
}
func Constructor() StockSpanner {
return StockSpanner{}
}
func (this *StockSpanner) Next(price int) int {
span := 1
for len(this.stack) > 0 && this.stack[len(this.stack)-1].price <= price {
// 如果当前栈顶price小于当前price,则当前span = 栈顶span + 1
// 然后还需要继续向栈底判断,如果还有小于当前price的pair则需要再次加上相应的span
span += this.stack[len(this.stack)-1].span
// 不断删除栈顶小于当前价格的pair
this.stack = this.stack[:len(this.stack)-1]
}
// 目前栈顶span价格大于当前price,则构造pair并加入栈顶
this.stack = append(this.stack, pair{price: price, span: span})
return span
}
/**
* Your StockSpanner object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Next(price);
*//**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func inorderTraversal(root *TreeNode) []int {
arr := make([]int, 0)
Inorder(root, &arr)
return arr
}
// 得传入切片指针
func Inorder(root *TreeNode, arr *[]int) {
if root == nil {
return
}
Inorder(root.Left, arr)
*arr = append(*arr, root.Val)
Inorder(root.Right, arr)
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isSymmetric(root *TreeNode) bool {
if root == nil {
return true
}
return compare(root.Left, root.Right)
}
func compare(left, right *TreeNode) bool {
// 处理空节点:一空一非 false,两空 true
if left == nil || right == nil {
return left == right
}
// 值不相等:不对称
if left.Val != right.Val {
return false
}
// 镜像递归:外侧 (left.Left ↔ right.Right),内侧 (left.Right ↔ right.Left)
return compare(left.Left, right.Right) && compare(left.Right, right.Left)
}func myPow(x float64, n int) float64 {
if n < 0 {
x = 1 / x
n = -n
}
if n == 0 {return 1}
if n == 1 {return x}
half := myPow(x, n / 2)
if n % 2 == 0 {
return half * half
} else {
return half * half * x
}
}
func majorityElement(nums []int) int {
if len(nums) == 1 {return nums[0]}
res := make(map[int]int)
for _, value := range nums {
if v, ok := res[value]; ok {
res[value] = v + 1
if res[value] > (len(nums) / 2) {
return value
}
} else {
res[value] = 1
}
}
return 0
}
func maxProfit(prices []int) int {
if len(prices) == 0 || len(prices) == 1 {return 0}
yesterday := prices[0]
res := 0
for i := 1; i < len(prices); i++ {
if yesterday < prices[i] {
res += (prices[i] - yesterday)
}
yesterday = prices[i]
}
return res
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func levelOrder(root *TreeNode) [][]int {
if root == nil {
return [][]int{}
}
queue := []*TreeNode{root} // 简化为字面量初始化
res := [][]int{}
for len(queue) > 0 {
levelSize := len(queue) // 当前层节点数(有效节点)
levelVals := []int{} // 当前层值
for i := 0; i < levelSize; i++ {
node := queue[0]
queue = queue[1:]
levelVals = append(levelVals, node.Val) // 假设无 nil 节点(标准树)
// 只追加非 nil 子节点
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
res = append(res, levelVals)
}
return res
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func minDepth(root *TreeNode) int {
// if root == nil {
// return 0
// }
// // 一旦根节点有子节点,那么根节点就不可能是叶子节点
// if root.Left == nil {
// return 1 + minDepth(root.Right)
// }
// if root.Right == nil {
// return 1 + minDepth(root.Left)
// }
// left := 1 + minDepth(root.Left)
// right := 1 + minDepth(root.Right)
// if left < right {
// return left
// }
// return right
return bfs(root)
}
func bfs(root *TreeNode) int {
if root == nil {return 0}
nodeQueue := []*TreeNode{root}
deep := 0
for len(nodeQueue) > 0 {
levelSize := len(nodeQueue)
for i := 0; i < levelSize; i++ {
if nodeQueue[i].Left == nil && nodeQueue[i].Right == nil {return deep+1}
if nodeQueue[i].Left != nil {
nodeQueue = append(nodeQueue, nodeQueue[i].Left)
}
if nodeQueue[i].Right != nil {
nodeQueue = append(nodeQueue, nodeQueue[i].Right)
}
}
nodeQueue = nodeQueue[levelSize:]
deep += 1
}
return deep
}
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxDepth(root *TreeNode) int {
// if root == nil {return 0}
// left := maxDepth(root.Left) + 1
// right := maxDepth(root.Right) + 1
// if left > right {
// return left
// }
// return right
return bfs(root)
}
func bfs(root *TreeNode) int {
if root == nil {return 0}
queue := []*TreeNode{root}
deep := 0
for len(queue) > 0 {
levelSize := len(queue)
for i := 0; i < levelSize; i++ {
if queue[i].Left != nil {
queue = append(queue, queue[i].Left)
}
if queue[i].Right != nil {
queue = append(queue, queue[i].Right)
}
}
deep += 1
queue = queue[levelSize:]
}
return deep
}
func bitwiseComplement(n int) int {
if n == 0 {
return 1
}
tmp, bit := n, 1
for tmp != 0 {
n = bit ^ n
bit = bit << 1
tmp = tmp >> 1 //用于判断整个数是否已经处理结束,结束时tmp为0
}
return n
}
func generateParenthesis(n int) []string {
res := make([]string, 0)
gen("", &res, n, n)
return res
}
//按照括号匹配规范生成括号串
func gen(s string, res *[]string, left, right int) {
if left == 0 && right == 0 {
*res = append(*res, s)
return
}
// 左括号只要有就可以加进去
if left > 0 {
gen(s+"(", res, left-1, right)
}
// 右括号必须在左括号数大于右括号数时才可以添加
if right > left {
gen(s+")", res, left, right-1)
}
}