力扣刷题日记
2024-10-24
92.反转链表||
标签
链表
给你单链表的头指针head和两个整数left和right,其中left<=right。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
输入:head = [5], left = 1, right = 1
输出:[5]
方法
局部反转链表,思路为在一次遍历中将当前节点的下一个放在局部链表的最前面,需要将pre和cur先遍历到left-1和left,借助最开始局部链表首节点cur的前一个节点pre,同时注意链表换位置的操作在代码中上一行的尾部是这一行的头部。

需要三个指针变量,pre,cur,tmp
pre:永远指向待反转区域的第一个节点left的前一个节点,pre不会改变
cur:指向待反转区域的第一个节点left
tmp:永远指向cur的下一个节点,循环过程中cur变化后tmp会变化
步骤如下:
- 记录
cur的下一个节点为tmp - 将
cur的下一个节点指向tmp的下一个节点 - 将
tmp的下一个节点指向pre的下一个节点 - 将
pre的下一个节点指向tmp
这样就将当前节点的下一个节点放在待排序区域[left,right]的首位置left了
图中的例子应为725436->752436->745236->734526
代码
1 | def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]: |
1535.找出数组游戏的赢家同3175. 找到连续赢 K 场比赛的第一位玩家
标签
数组 模拟
给你一个由 不同 整数组成的整数数组 arr 和一个整数 k 。
每回合游戏都在数组的前两个元素(即 arr[0] 和 arr[1] )之间进行。比较 arr[0] 与 arr[1] 的大小,较大的整数将会取得这一回合的胜利并保留在位置 0 ,较小的整数移至数组的末尾。当一个整数赢得 k 个连续回合时,游戏结束,该整数就是比赛的 赢家 。
返回赢得比赛的整数。
输入:arr = [2,1,3,5,4,6,7], k = 2
输出:5
解释:一起看一下本场游戏每回合的情况:

因此将进行 4 回合比赛,其中 5 是赢家,因为它连胜 2 回合。
输入:arr = [3,2,1], k = 10
输出:3
解释:3 将会在前 10 个回合中连续获胜。
输入:arr = [1,9,8,2,3,7,6,4,5], k = 7
输出:9
思路
由于较小的元素会移至数组的末尾,在重新遇到被移至数组末尾的元素之前,arr 的每个元素都会被访问到。
考察游戏执行的流程,本质上是在从左到右遍历 arr,求数组最大值(打擂台)。我们要找首个连续 k 回合都是最大值的数。
如果遍历完 arr 也没找到这样的数,那么答案就是 arr 的最大值 mx,因为此时比 mx 小的数都会移到 mx 的右边,所以后面比大小都是 mx 胜利。
具体算法
- 初始化
mx=arr[0],win=0,从arr[1]开始遍历数组。其中win用来统计mx连续多少个回合是最大值(获胜)。 - 如果
arr[i]>mx,更新mx=arr[i]以及win=0。 - 把
win加一,如果win=k就退出循环。 - 遍历结束(或者中途退出循环),返回
mx。
代码
1 | def getWinner(self, arr: List[int], k: int) -> int: |
2024-10-27
684.冗余连接
标签
深度优先搜索、广度优先搜索、并查集
树可以看成是一个连通且 无环 的 无向 图。
给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。
请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的那个。
输入: edges = [[1,2], [1,3], [2,3]]
输出: [2,3]
输入: edges = [[1,2], [2,3], [3,4], [1,4], [1,5]]
输出: [1,4]
方法:并查集
树中边的数量=点的数量-1,这道题中的图在树的基础上多了一条边,所以节点数量=边的数量=n。
树是一个连通且无环的无向图,在树中多了一条附加的边之后就会出现环,因此附加的边是导致环出现的边。
可以通过并查集寻找附加的边。初始时,每个节点都属于不同的连通分量。遍历每一条边,判断这条边连接的两个顶点是否属于相同的连通分量。
· 如果两个顶点属于不同的连通分量,则说明在遍历到当前的边之前,这两个顶点之间不连通,因此当前的边不会导致出现环,合并这两个顶点的连通分量。
· 如果两个顶点属于相同的连通分量,则说明在遍历到当前的边之前,这两个顶点之间已经连通,因此当前的边会导致出现环,是附加的边,返回当前的边作为结果
代码
1 | class Solution: |
2024-10-29
17.电话号码的字母组合
标签
哈希表、字符串、回溯
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
输入:digits = ""
输出:[]
输入:digits = "2"
输出:["a","b","c"]
方法:回溯
使用mapping数组模拟哈希表对数字和电话号码进行映射,回溯中判断添加到结果数组res中,用法是res.append("".join(arr)),join函数的执行逻辑为将列表arr中的每个元素间隔""拼接起来,在进行添加字符和删除的过程中,参数arr不是字符串(字符串不能进行append和pop操作),而是list列表,所以要使用dfs([])来调用函数,如果要使用参数arr为字符串的话,for循环中的操作应该为arr += x,dfs(arr),arr = arr[:-1],调用函数应该为dfs("")
代码
1 | def letterCombinations(self, digits: str) -> List[str]: |
动态规划
1 | def maxEnergyBoost(self, energyDrinkA: List[int], energyDrinkB: List[int]) -> int: |