LeetCode第232场周赛(4道题——python)

相关链接可点击:

1790. 仅执行一次字符串交换能否使两个字符串相等

1791. 找出星型图的中心节点

1792. 最大平均通过率

1793. 好子数组的最大分数


目录

1790_仅执行一次字符串交换能否使两个字符串相等

一、题目

二、示例

三、思路

四、代码

1791_找出星型图的中心节点

一、题目

二、示例

三、思路

四、代码

1792_最大平均通过率

一、题目

二、示例

三、思路

四、代码

1793_好子数组的最大分数

一、题目

二、示例

三、思路

四、代码


1790_仅执行一次字符串交换能否使两个字符串相等

一、题目

给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符

如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false

二、示例

示例 1:

输入:s1 = "bank", s2 = "kanb"
输出:true
解释:例如,交换 s2 中的第一个和最后一个字符可以得到 "bank"

示例 2:

输入:s1 = "attack", s2 = "defend"
输出:false
解释:一次字符串交换无法使两个字符串相等

示例 3:

输入:s1 = "kelb", s2 = "kelb"
输出:true
解释:两个字符串已经相等,所以不需要进行字符串交换

示例 4:

输入:s1 = "abcd", s2 = "dcba"
输出:false

提示:

  • 1 <= s1.length, s2.length <= 100
  • s1.length == s2.length
  • s1 和 s2 仅由小写英文字母组成

三、思路

题意:

字符串交换:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符;

返回:对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false

根据题意可知,字符交换只有 0 次或 1 次,即不同字符的个数只能有 0 个或 2 个。

因此,思路为:

  1. 循环遍历两个字符串,找出两个字符串中不同字符的下标,并用变量 index1 和 index2 存储
  2. 如果两字符串中的字符超过两个,则返回 False
  3. 如果不同字符只有 2 个,则需要判断:
  4. 字符串s1的第一个不同字符 与 字符串s2 的第二个不同字符 是否相等;
  5. 字符串s1的第二个不同字符 与 字符串s2 的第一个不同字符 是否相等;
  6. 若满足以上两点,返回 True;否则,返回 False。

例如:s1 = "bank", s2 = "kanb"

s1[0] == s2[3] == b  且  s1[3] == s2[0] == k,返回True

例如:s1 = "bank", s2 = "kanc"

s1[0] != s2[3] ,返回False

四、代码

class Solution:
    def areAlmostEqual(self, s1: str, s2: str) -> bool:
        index1, index2 = -1, -1
        for i in range(len(s1)):
            if s1[i] != s2[i]:
                if index1 == -1:
                    index1 = i
                elif index1 != -1 and index2 == -1:
                    index2 = i
                else:
                    return False
        return s1[index1] == s2[index2] and s1[index2] == s2[index1]

if __name__ == '__main__':
    s1 = "bank"
    s2 = "kanb"
    s = Solution()
    ans = s.areAlmostEqual(s1, s2)
    print(ans)

1791_找出星型图的中心节点

一、题目

有一个无向的 星型 ,由 n 个编号从 1 到 n 的节点组成。星型图有一个 中心 节点,并且恰有 n - 1 条边将中心节点与其他每个节点连接起来。

给你一个二维整数数组 edges ,其中 edges[i] = [ui, vi] 表示在节点 ui 和 vi 之间存在一条边。请你找出并返回 edges 所表示星型图的中心节点。

二、示例

示例 1:


输入:edges = [[1,2],[2,3],[4,2]]
输出:2
解释:如上图所示,节点 2 与其他每个节点都相连,所以节点 2 是中心节点。

示例 2:

输入:edges = [[1,2],[5,1],[1,3],[1,4]]
输出:1

提示:

  • 3 <= n <= 105
  • edges.length == n - 1
  • edges[i].length == 2
  • 1 <= ui, vi <= n
  • ui != vi
  • 题目数据给出的 edges 表示一个有效的星型图

三、思路

题意:

无向的 星型 图:由 n 个编号从 1 到 n 的节点组成,例如:

中心节点:恰有 n - 1 条边将中心节点与其他每个节点连接起来,如上图中的数字2

edges[i] = [ui, vi] 表示在节点 ui 和 vi 之间存在一条边

例如:edges = [[1,2],[2,3],[4,2]] 中的中心节点 2 在每一个edges[i] 均出现。

因此,思路为:

  1. 求出每个节点出现的次数,利用dict字典记录
  2. 返回出现次数最大且次数等于 n - 1 的节点,否则,返回 -1

四、代码

class Solution:
    def findCenter(self, edges) -> int:
        """
        :param edges: List[List[int]]
        :return: int
        """
        nums = dict()
        for edge in edges:
            if edge[0] not in nums:
                nums[edge[0]] = 1
            else:
                nums[edge[0]] += 1
            if edge[1] not in nums:
                nums[edge[1]] = 1
            else:
                nums[edge[1]] += 1
        # print(nums)
        max_value = max(nums.values())
        if max_value == len(nums) - 1:
            return [k for k, v in nums.items() if v == max_value][0]

if __name__ == '__main__':
    s = Solution()
    edges = [[1, 2], [2, 3], [4, 2]]
    ans = s.findCenter(edges)
    print(ans)

1792_最大平均通过率

一、题目

一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组 classes ,其中 classes[i] = [passi, totali] ,表示你提前知道了第 i 个班级总共有 totali 个学生,其中只有 passi 个学生可以通过考试。

给你一个整数 extraStudents ,表示额外有 extraStudents 个聪明的学生,他们 一定 能通过任何班级的期末考。你需要给这 extraStudents 个学生每人都安排一个班级,使得 所有 班级的 平均 通过率 最大 。

一个班级的 通过率 等于这个班级通过考试的学生人数除以这个班级的总人数。平均通过率 是所有班级的通过率之和除以班级数目。

请你返回在安排这 extraStudents 个学生去对应班级后的 最大 平均通过率。与标准答案误差范围在 10-5 以内的结果都会视为正确结果。

二、示例

示例 1:

输入:classes = [[1,2],[3,5],[2,2]], extraStudents = 2
输出:0.78333
解释:你可以将额外的两个学生都安排到第一个班级,平均通过率为 (3/4 + 3/5 + 2/2) / 3 = 0.78333 。

示例 2:

输入:classes = [[2,4],[3,9],[4,5],[2,10]], extraStudents = 4
输出:0.53485

提示:

  • 1 <= classes.length <= 10 ^ 5
  • classes[i].length == 2
  • 1 <= passi <= totali <= 10 ^ 5
  • 1 <= extraStudents <= 10 ^ 5

三、思路

题意:

二维数组 classes: classes[i] = [passi, totali], 表示第 i 个班级总共有 totali 个学生,其中只有 passi 个学生可以通过考试

整数 extraStudents:表示额外有 extraStudents 个聪明的学生,他们 一定 能通过任何班级的期末考

通过率:等于这个班级通过考试的学生人数除以这个班级的总人数,即 通过率 = pass / total

平均通过率:所有班级的通过率之和除以班级数目,即 平均通过率 = (通过率1 + 通过率2 + ... + 通过率n) / n

需要给这 extraStudents 个学生每人都安排一个班级,使得 所有 班级的 平均 通过率 最大 

返回:最大平均通过率

因此,思路为:

  1. 在安排一个聪明学生进班级前,需求出放入后与放入前该班级的通过率之差,即 通过率之差 = (pass + 1) / (total + 1) - pass / total
  2. 将一个聪明学生放入通过率差值最大的班级
  3. 重复步骤1,2,直至所有聪明的学生均已安排完毕

在这里,由于每次都需要对各班级的通过率之差进行排序,时间复杂度较高, 因此这里采用了堆排序对通过率之差进行排序。

python 中有内置函数,可直接调用,非常方便!

补充知识:

  • import heapq:导入库函数,这里指的是小堆
  • heapq.heappush(heap, item):heap堆中添加元素item
  • heapq.heappop(heap):删除heap堆中的最小元素
  • heapq.heapreplace(heap, item):删除heap堆中的最小元素,并添加元素item 

四、代码

import heapq
class Solution:
    def maxAverageRatio(self, classes, extraStudents: int) -> float:
        """
        :param classes: List[List[int]]
        :param extraStudents: int
        :return: float
        """
        heap = []  # 堆
        for singleclass in classes:
            tmp = (singleclass[0] + 1) / (singleclass[1] + 1) - (singleclass[0]) / (singleclass[1])
            heapq.heappush(heap, [-tmp] + singleclass)

        while extraStudents > 0:
            first = heap[0]
            first[1] += 1
            first[2] += 1
            tmp = ((first[1] + 1) / (first[2] + 1)) - (first[1] / first[2])
            first[0] = -tmp
            heapq.heapreplace(heap, first)
            extraStudents -= 1
        ans = 0.0
        while len(heap):
            node = heapq.heappop(heap)
            ans += node[1] / node[2]
        return ans / len(classes)

if __name__ == '__main__':
    classes = [[2, 4], [3, 9], [4, 5], [2, 10]]
    extraStudents = 4
    s = Solution()
    ans = s.maxAverageRatio(classes, extraStudents)
    # ans = 0.53485
    print(ans)

1793_好子数组的最大分数

一、题目

给你一个整数数组 nums (下标从 0 开始)和一个整数 k 。

一个子数组 (i, j) 的 分数 定义为 min(nums[i], nums[i+1], ..., nums[j]) * (j - i + 1) 

一个 好 子数组的两个端点下标需要满足 i <= k <= j 

请你返回 好 子数组的最大可能 分数 

二、示例

示例 1:

输入:nums = [1,4,3,7,4,5], k = 3
输出:15
解释:最优子数组的左右端点下标是 (1, 5) ,分数为 min(4,3,7,4,5) * (5-1+1) = 3 * 5 = 15 。

示例 2:

输入:nums = [5,5,4,5,4,1,1,1], k = 0
输出:20
解释:最优子数组的左右端点下标是 (0, 4) ,分数为 min(5,5,4,5,4) * (4-0+1) = 4 * 5 = 20 。

提示:

  • 1 <= nums.length <= 10 ^ 5
  • 1 <= nums[i] <= 2 * 10 ^ 4
  • 0 <= k < nums.length

三、思路

题意:

子数组 (i, j) 的 分数:min(nums[i], nums[i+1], ..., nums[j]) * (j - i + 1) 

好子数组(i, j):满足 i <= k <= j 

返回:好子数组的最大可能分数

因此,思路为:

以下标k为中心,向左,向右进行滑动

  • nums[right] >= nums[k] : right + 1
  • nums[left] >= nums[k] : left - 1

直到左右边界都出现比nums[k]小的数,计算最大可能分数 ans = (right - left - 1) * nums[k]

四、代码

class Solution:
    def maximumScore(self, nums, k: int) -> int:
        """
        :param nums: List[int]
        :param k: int
        :return: int
        """
        ans = 0
        n = len(nums)
        left, right = k, k
        for i in range(nums[k], 0, -1):
            while left >= 0 and nums[left] >= i:
                left -= 1
            while right < n and nums[right] >= i:
                right += 1
            ans = max(ans, (right - left - 1) * i)
            if left < 0 and right == n:
                break
        return ans

if __name__ == '__main__':
    nums = [1, 4, 3, 7, 4, 5]
    k = 3
    s = Solution()
    ans = s.maximumScore(nums, k)
    print(ans)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值