【CodeTop】TOP 100 刷题 31-40

2023-12-06 13:20
文章标签 100 top 31 刷题 40 codetop

本文主要是介绍【CodeTop】TOP 100 刷题 31-40,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 31. 二叉树中的最大路径和
    • 题目描述
    • 代码与解题思路
  • 32. 合并区间
    • 题目描述
    • 代码与解题思路
  • 33. 编辑距离
    • 题目描述
    • 代码与解题思路
  • 34. 二叉树的中序遍历
    • 题目描述
    • 代码与解题思路
  • 35. 最长公共子序列
    • 题目描述
    • 代码与解题思路
  • 36. 二分查找
    • 题目描述
    • 代码与解题思路
  • 37. 二叉树的右视图
    • 题目描述
    • 代码与解题思路
  • 38. 用栈实现队列
    • 题目描述
    • 代码与解题思路
  • 39. 删除排序链表中的重复元素 II
    • 题目描述
    • 代码与解题思路
  • 40. 寻找两个正序数组的中位数
    • 题目描述
    • 代码与解题思路

31. 二叉树中的最大路径和

题目链接:124. 二叉树中的最大路径和

题目描述

代码与解题思路

func maxPathSum(root *TreeNode) int {ans := math.MinIntvar dfs func(*TreeNode) intdfs = func(node *TreeNode) int {if node == nil {return 0}left := dfs(node.Left)right := dfs(node.Right)ans = max(ans, left+right+node.Val)return max(node.Val+max(left, right), 0)}dfs(root)return ans
}

树形 DP,推荐学习:https://www.bilibili.com/video/BV17o4y187h1/

32. 合并区间

题目链接:56. 合并区间

题目描述

代码与解题思路

func merge(intervals [][]int) [][]int {sort.Slice(intervals, func(i, j int) bool {return intervals[i][0] < intervals[j][0]})res := [][]int{}pre := intervals[0]for i := 1; i < len(intervals); i++ {cur := intervals[i]if pre[1] < cur[0] { // 区间不重合了, 追加到 res 数组res = append(res, pre)pre = cur} else { // 区间重合, 扩大区间范围pre[1] = max(cur[1], pre[1])}}res = append(res, pre) // 剩下最后一个没法合并的区间, 直接追加return res
}

画图模拟即可,顺便学习一下如何排序二维数组:

sort.Slice(intervals, func(i, j int) bool {return intervals[i][0] < intervals[j][0]
})

33. 编辑距离

题目链接:72. 编辑距离

题目描述

代码与解题思路

func minDistance(word1 string, word2 string) int {n, m := len(word1), len(word2)// 创建 dp 数组dp := make([][]int, n+1)for i := 0; i < len(dp); i++ {dp[i] = make([]int, m+1)}// 初始化for i := 0; i <= n; i++ {dp[i][0] = i}for i := 0; i <= m; i++ {dp[0][i] = i}// 填表for i, v1 := range word1 {for j, v2 := range word2 {if v1 == v2 {dp[i+1][j+1] = dp[i][j]} else {dp[i+1][j+1] = min(min(dp[i+1][j], dp[i][j+1]), dp[i][j])+1}}}return dp[n][m]
}

dp 问题的核心就是状态转移方程的推导,通过分类讨论题目要求,我们能得出有这几种情况:

  1. 两个字母相同,不需要修改 dp[ i+1 ][ j+1 ] = dp[ i ][ j ]
  2. 两个字母不同分三种情况:
    1. word1 缺失,只需要进行一个删除操作即可 dp[ i+1 ][ j ] + 1
    2. word2 缺失,只需要进行一个删除操作即可 dp[ i ][ j+1 ] + 1
    3. word1 和 word2 字母不相同,进行替换操作即可 dp[ i+1 ][ j+1 ] + 1

最后取第二种情况的最小值即可,因为要求最少的操作次数

最后就是初始化 dp 数组,从左往右,从上往下按顺序填表

省流:熟练的默写动态规划的套路罢了,到底懂没懂不好说

34. 二叉树的中序遍历

题目链接:94. 二叉树的中序遍历

题目描述

代码与解题思路

先来个递归解法:

func inorderTraversal(root *TreeNode) (ans []int) {var inorder func(*TreeNode)inorder = func(root *TreeNode) {if root == nil {return}inorder(root.Left)ans = append(ans, root.Val)inorder(root.Right)}inorder(root)return ans
}

非递归:

// 记住中序遍历顺序:左根右
func inorderTraversal(root *TreeNode) (ans []int) {st := list.New()cur := rootfor cur != nil || st.Len() > 0 {if cur != nil { // 找最左节点st.PushBack(cur)cur = cur.Left} else { // 栈顶是最左节点了cur = st.Remove(st.Back()).(*TreeNode)ans = append(ans, cur.Val) // 取值cur = cur.Right // 找右}}return ans
}

我们来根据代码梳理一下他的流程

  1. 将当前节点入栈,然后一直往左遍历直到走到 nil
  2. 走到 nil 之后,上一个节点,也就是栈顶的元素就是最左节点,输出到 ans然后往右遍历一步,持续这个三步循环

这三步模拟的就是 “左根右” 的遍历方式,刚好也是三步,找到最左,取根,找右,循环往复,就能完成中序遍历了。

迭代算法确实不太好想,但是上手模拟一遍还是比较好理解的。

35. 最长公共子序列

题目链接:1143. 最长公共子序列

题目描述

代码与解题思路

func longestCommonSubsequence(text1 string, text2 string) int {n, m := len(text1), len(text2)dp := make([][]int, n+1)for i := 0; i < n+1; i++ {dp[i] = make([]int, m+1)}for i, v1 := range text1 {for j, v2 := range text2 {if v1 == v2 {dp[i+1][j+1] = dp[i][j] + 1} else {dp[i+1][j+1] = max(dp[i+1][j], dp[i][j+1])}}}return dp[n][m]
}

这道题需要注意的是,子序列和子数组,子数组必须是连续的,而子序列不一定。所以子序列相关的题目是经典的动态规划类型题目,所以我们首先分析题目然后写出状态转移方程:

  1. 如果两个字母相同,dp[ i+1 ][ j+1 ] = dp[ i ][ j ] + 1
  2. 如果两个字母不相同,看看之前有没有出现过相同的子序列,继承一下最长子序列的长度:dp[ i+1 ][ j+1 ] = max(dp[ i+1 ][ j ], dp[ i ][ j+1 ])

看图:

接着就是愉快的默写,初始化 dp 数组,填表,返回。

36. 二分查找

题目链接:704. 二分查找

题目描述

代码与解题思路

func search(nums []int, target int) int {left, right := 0, len(nums)-1for left <= right {mid := left+(right-left)/2if nums[mid] < target {left = mid+1} else if nums[mid] > target {right = mid-1} else {return mid}}return -1
}

经典二分,熟练二分的思想,思考和控制好二分的边界,那二分用起来就不困难。

37. 二叉树的右视图

题目链接:199. 二叉树的右视图

题目描述

代码与解题思路

func rightSideView(root *TreeNode) (ans []int) {if root == nil {return nil}Queue := []*TreeNode{root}for len(Queue) > 0 {n := len(Queue)nextQueue := []*TreeNode{}for n > 0 {cur := Queue[0]Queue = Queue[1:]if cur.Left != nil {nextQueue = append(nextQueue, cur.Left)}if cur.Right != nil {nextQueue = append(nextQueue, cur.Right)}n--if n == 0 {ans = append(ans, cur.Val)}}Queue = nextQueue}return ans
}

今天真是头昏了,被层序玩傻了,下次写层序遍历用土方法吧,先画图,然后对照着图的思路来写层序遍历,不要浪了,踏踏实实才是真本领,再怎么背模板总会忘记的,融会贯通才是最重要的。

38. 用栈实现队列

题目链接:232. 用栈实现队列

题目描述

代码与解题思路

type MyQueue struct {st1 []intst2 []int
}func Constructor() MyQueue {return MyQueue{st1: []int{},st2: []int{},}
}func (q *MyQueue) Push(x int)  {q.st1 = append(q.st1, x)
}func (q *MyQueue) Pop() int {st1ToSt2(q)front := q.st2[len(q.st2)-1]q.st2 = q.st2[:len(q.st2)-1]return front
}func (q *MyQueue) Peek() int {st1ToSt2(q)return q.st2[len(q.st2)-1]
}func st1ToSt2(q *MyQueue) { // 抽象出数据流转操作if len(q.st2) == 0 {n := len(q.st1) // 注意, 因为后续操作会影响到 q.st1for i := 0; i < n; i++ {q.st2 = append(q.st2, q.st1[len(q.st1)-1]) q.st1 = q.st1[:len(q.st1)-1]}}
}func (q *MyQueue) Empty() bool {if len(q.st1) == 0 && len(q.st2) == 0 {return true}return false
}

这里有个需要注意的地方,就是在遍历的时候会改变 q.st1 数组的大小,所以在使用 for 循环的时候需要提前求出 n := len(q.st1) 然后使用 n,而不能直接使用 len(q.st1) 作为判断的条件

39. 删除排序链表中的重复元素 II

题目链接:82. 删除排序链表中的重复元素 II

题目描述

代码与解题思路

func deleteDuplicates(head *ListNode) *ListNode {phead := &ListNode{Next: head}cur := phead // cur 一直保持在前一个节点这个相对位置for cur.Next != nil && cur.Next.Next != nil {nVal, nnVal := cur.Next.Val, cur.Next.Next.Valif nnVal == nVal { // 如果出现相同的情况, 就跳过重复节点for cur.Next != nil && cur.Next.Val == nVal {cur.Next = cur.Next.Next}} else {cur = cur.Next}}return phead.Next
}

这个是练习链表的基本功问题,下次遇到再重新做做,检测一下自己的链表内功。

40. 寻找两个正序数组的中位数

题目链接:4. 寻找两个正序数组的中位数

题目描述

代码与解题思路

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {nums1 = append(nums1, nums2...)sort.Ints(nums1)if len(nums1)%2!=0 {return float64(nums1[len(nums1)/2])}return float64(nums1[len(nums1)/2-1]+nums1[len(nums1)/2])/2
}

这道题比较难,所以我决定开摆,直接合并数组+排序一气呵成。

这篇关于【CodeTop】TOP 100 刷题 31-40的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/461970

相关文章

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

Linux 删除 当前下的 mysql-8.0.31 空文件夹

在Linux中,如果你想要删除当前目录下的名为mysql-8.0.31的空文件夹(即该文件夹内没有任何文件或子文件夹),你可以使用rmdir命令。但是,如果mysql-8.0.31文件夹并非完全为空(即它包含文件或子文件夹),rmdir命令会失败。 如果你的目标是删除mysql-8.0.31文件夹及其内部的所有内容(无论是否为空),你应该使用rm命令结合-r(或-R,它们是等价的)选项来递归地删

【LeetCode热题100】前缀和

这篇博客共记录了8道前缀和算法相关的题目,分别是:【模版】前缀和、【模版】二维前缀和、寻找数组的中心下标、除自身以外数组的乘积、和为K的子数组、和可被K整除的子数组、连续数组、矩阵区域和。 #include <iostream>#include <vector>using namespace std;int main() {//1. 读取数据int n = 0, q = 0;ci

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II 1.题目 1.1递增子序列 题目链接:491. 非递减子序列 - 力扣(LeetCode) 视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0491.%E9%80%92%E

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

诺瓦星云校招嵌入式面试题及参考答案(100+面试题、10万字长文)

SPI 通信有哪些内核接口? 在嵌入式系统中,SPI(Serial Peripheral Interface,串行外设接口)通信通常涉及以下内核接口: 时钟控制接口:用于控制 SPI 时钟的频率和相位。通过设置时钟寄存器,可以调整 SPI 通信的速度以适应不同的外设需求。数据发送和接收接口:负责将数据从主机发送到从机以及从从机接收数据到主机。这些接口通常包括数据寄存器,用于存储待发

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II 1.题目 1.1复原IP地址 题目链接:93. 复原 IP 地址 - 力扣(LeetCode) 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0093.%E5%A4%8

【笔记】数据结构刷题09

快速排序 215. 数组中的第K个最大元素 class Solution {public:int findKthLargest(vector<int>& nums, int k) {return divide(nums,0,nums.size()-1,nums.size()-k);}int divide(vector<int>& nums,int left,int right,int k)