【Python 算法零基础 2.模拟 ③ 基于链表】

目录

基于链表

Ⅰ、2181. 合并零之间的节点

思路与算法 

① 初始化

② ​遍历链表

③ 返回结果

Ⅱ、1823. 找出游戏的获胜者

思路与算法

① ​初始化

② 淘汰过程

③ 返回结果


春天这么美,幸好没有腐烂在冬天

                                                —— 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. 从第 1 名小伙伴所在位置 开始 。
  2. 沿着顺时针方向数 k 名小伙伴,计数时需要 包含 起始时的那位小伙伴。逐个绕圈进行计数,一些小伙伴可能会被数过不止一次。
  3. 你数到的最后一名小伙伴需要离开圈子,并视作输掉游戏。
  4. 如果圈子中仍然有不止一名小伙伴,从刚刚输掉的小伙伴的 顺时针下一位 小伙伴 开始,回到步骤 2 继续执行。
  5. 否则,圈子中最后一名小伙伴赢得游戏。

给你参与游戏的小伙伴总数 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]

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值