目录
春天这么美,幸好没有腐烂在冬天
—— 25.3.20
基于链表
利用链表的数据结构,根据题目要求,去实现算法,如:
Ⅰ、2181. 合并零之间的节点
给你一个链表的头节点
head
,该链表包含由0
分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足Node.val == 0
。对于每两个相邻的
0
,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有0
移除,修改后的链表不应该含有任何0
。返回修改后链表的头节点
head
。示例 1:
输入:head = [0,3,1,0,4,5,2,0] 输出:[4,11] 解释: 上图表示输入的链表。修改后的链表包含: - 标记为绿色的节点之和:3 + 1 = 4 - 标记为红色的节点之和:4 + 5 + 2 = 11示例 2:
输入:head = [0,1,0,3,0,2,2,0] 输出:[1,3,4] 解释: 上图表示输入的链表。修改后的链表包含: - 标记为绿色的节点之和:1 = 1 - 标记为红色的节点之和:3 = 3 - 标记为黄色的节点之和:2 + 2 = 4提示:
- 列表中的节点数目在范围
[3, 2 * 105]
内0 <= Node.val <= 1000
- 不 存在连续两个
Node.val == 0
的节点- 链表的 开端 和 末尾 节点都满足
Node.val == 0
思路与算法
① 初始化
res 和 tail 都指向一个虚拟头节点(ListNode()
)。res
用于保存新链表的头节点,tail
用于迭代和构建新链表。
sum 用于累加连续的非零节点值。
cur 从 head.next
开始遍历链表,跳过第一个节点(因为第一个节点值通常为 0
)。
② 遍历链表
如果当前节点值 cur.val
不为 0
,则将其值累加到 sum
中。
如果当前节点值为 0
,表示一个连续非零段的结束,此时:
创建一个新节点 node
,其值为累加的 sum
。
将 tail.next
指向 node
,将 tail
移动到 node
,表示将新节点添加到新链表中。
重置 sum
为 0
,准备累加下一段连续非零值。
③ 返回结果
遍历结束后,返回 res.next
,即新链表的第一个有效节点(跳过虚拟头节点)。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
res = tail = ListNode()
sum = 0
i = 0
cur = head.next
while cur:
if cur.val != 0:
sum += cur.val
else:
node = ListNode(val = sum)
tail.next = node
tail = tail.next
sum = 0
cur = cur.next
return res.next
Ⅱ、1823. 找出游戏的获胜者
共有
n
名小伙伴一起做游戏。小伙伴们围成一圈,按 顺时针顺序 从1
到n
编号。确切地说,从第i
名小伙伴顺时针移动一位会到达第(i+1)
名小伙伴的位置,其中1 <= i < n
,从第n
名小伙伴顺时针移动一位会回到第1
名小伙伴的位置。游戏遵循如下规则:
- 从第
1
名小伙伴所在位置 开始 。- 沿着顺时针方向数
k
名小伙伴,计数时需要 包含 起始时的那位小伙伴。逐个绕圈进行计数,一些小伙伴可能会被数过不止一次。- 你数到的最后一名小伙伴需要离开圈子,并视作输掉游戏。
- 如果圈子中仍然有不止一名小伙伴,从刚刚输掉的小伙伴的 顺时针下一位 小伙伴 开始,回到步骤
2
继续执行。- 否则,圈子中最后一名小伙伴赢得游戏。
给你参与游戏的小伙伴总数
n
,和一个整数k
,返回游戏的获胜者。示例 1:
输入:n = 5, k = 2 输出:3 解释:游戏运行步骤如下: 1) 从小伙伴 1 开始。 2) 顺时针数 2 名小伙伴,也就是小伙伴 1 和 2 。 3) 小伙伴 2 离开圈子。下一次从小伙伴 3 开始。 4) 顺时针数 2 名小伙伴,也就是小伙伴 3 和 4 。 5) 小伙伴 4 离开圈子。下一次从小伙伴 5 开始。 6) 顺时针数 2 名小伙伴,也就是小伙伴 5 和 1 。 7) 小伙伴 1 离开圈子。下一次从小伙伴 3 开始。 8) 顺时针数 2 名小伙伴,也就是小伙伴 3 和 5 。 9) 小伙伴 5 离开圈子。只剩下小伙伴 3 。所以小伙伴 3 是游戏的获胜者。示例 2:
输入:n = 6, k = 5 输出:1 解释:小伙伴离开圈子的顺序:5、4、6、2、3 。小伙伴 1 是游戏的获胜者。提示:
1 <= k <= n <= 500
思路与算法
① 初始化
list(range(1, n + 1)):生成一个包含从 1 到 n 的连续整数的列表
创建一个列表 arr
,包含从 1 到 n 的编号,表示参与游戏的人。
初始化变量 i
为 0,表示当前开始计数的位置。
② 淘汰过程
使用 while
循环,直到圈中只剩下一人(n > 1
)。
计算下一个被淘汰的人的位置:i = (i + k - 1) % n
。这里 (i + k - 1) % n
确保计数是循环的,且步长为 k。
使用 arr.pop(i)
淘汰当前位置的人,并将圈中人数 n
减 1。
③ 返回结果
当圈中只剩下一人时,返回 arr[0]
,即获胜者的编号。
class Solution:
def findTheWinner(self, n: int, k: int) -> int:
arr = list(range(1, n + 1))
i = 0
while n > 1:
i = (i + k -1) % n
arr.pop(i)
n -= 1
return arr[0]