青训营题目歌曲的时长配对问题+小s的倒排索引题解

2 阅读4分钟

歌曲的时长配对问题

1.问题描述

小F有一个由歌曲组成的列表,每首歌的持续时间用数组 time 表示,其中第 i 首歌的时长为 time[i] 秒。她想知道列表中有多少对歌曲的总持续时间能够被 10 整除。具体来说,我们希望找到所有满足 i < j 且 (time[i] + time[j]) % 10 == 0 的配对。

2.解题思路

2.1问题分析

我们需要找到所有满足 i < j 且 (time[i] + time[j]) % 10 == 0 的配对。这意味着我们需要检查每一对歌曲的时长和是否能被 10 整除

2.2基本思路

  1. 遍历数组:我们可以通过遍历数组来检查每一对歌曲的时长和。
  2. 使用哈希表:为了提高效率,我们可以使用哈希表来记录每个余数的出现次数。这样我们可以在遍历过程中快速查找互补余数。

2.3示例

假设我们有数组 time = [7, 3, 5, 5, 10]

  • 7 的余数是 7
  • 3 的余数是 3
  • 5 的余数是 5
  • 5 的余数是 5
  • 10 的余数是 0

我们需要找到所有满足 (time[i] + time[j]) % 10 == 0 的配对。

2.4代码

def solution(time: list) -> int:
    # 初始化一个字典来记录每个余数的出现次数
    remainder_count = {}
    pair_count = 0
    
    # 遍历数组 time
    for t in time:
        # 计算当前歌曲时长的余数
        remainder = t % 10
        
        # 计算互补余数
        complement_remainder = (10 - remainder) % 10
        
        # 检查互补余数是否在字典中
        if complement_remainder in remainder_count:
            # 如果存在,则增加配对计数
            pair_count += remainder_count[complement_remainder]
        
        # 更新当前余数的计数
        if remainder in remainder_count:
            remainder_count[remainder] += 1
        else:
            remainder_count[remainder] = 1
    
    return pair_count

# 测试样例
print(solution([3, 2, 15, 1, 4]) == 0)  # 输出: True
print(solution([10, 20, 30]) == 3)  # 输出: True
print(solution([7, 3, 5, 5, 10]) == 2)  # 输出: True

3.代码详解

  1. 初始化哈希表remainder_count = {} 用于记录每个余数的出现次数。

  2. 遍历数组for t in time 遍历数组中的每个元素。

  3. 计算余数remainder = t % 10 计算当前歌曲时长的余数。

  4. 计算互补余数complement_remainder = (10 - remainder) % 10 计算互补余数。

  5. 检查并更新哈希表

    • 如果 complement_remainder 在 remainder_count 中,则增加 pair_count
    • 更新 remainder_count 中 remainder 的计数。

通过这种方式,我们可以高效地找到所有满足条件的配对。

小s的倒排索引

1.问题描述

小S正在帮助她的朋友们建立一个搜索引擎。为了让用户能够更快地找到他们感兴趣的帖子,小S决定使用倒排索引。倒排索引的工作原理是:每个单词都会关联一个帖子ID的列表,这些帖子包含该单词,且ID按从小到大的顺序排列。例如,单词“夏天”可能出现在帖子1、帖子3和帖子7中,那么这个单词的倒排链就是 [1, 3, 7]。如果用户想同时找到包含“夏天”和“海滩”的帖子,小S需要找出两个倒排链的交集,且将结果按照从大到小的顺序输出。现在,给定两个单词的倒排链数组 a 和 b,请你帮助小S找出同时包含这两个单词的帖子ID,并按从大到小的顺序返回结果。

2.解题思路

2.1问题分析

我们需要找到两个有序数组 a 和 b 的交集,并将结果按从大到小的顺序输出。由于输入的两个数组是有序的,我们可以使用双指针算法来高效地解决这个问题。

2.2基本思路

  1. 初始化两个指针:分别指向数组 a 和 b 的开头。

  2. 遍历两个数组:使用双指针遍历两个数组,比较指针指向的元素:

    • 如果 a[i] 等于 b[j],则将 a[i] 加入结果列表,并将两个指针都向前移动一位。
    • 如果 a[i] 小于 b[j],则将 i 向前移动一位。
    • 如果 a[i] 大于 b[j],则将 j 向前移动一位。
  3. 反转结果列表:将结果列表反转,以满足从大到小的顺序输出。

2.3示例

示例1

  • 输入:a = [1, 2, 3, 7], b = [2, 5, 7]
  • 输出:[7, 2]

示例2

  • 输入:a = [1, 4, 8, 10], b = [2, 4, 8, 10]
  • 输出:[10, 8, 4]

示例3

  • 输入:a = [3, 5, 9], b = [1, 4, 6]
  • 输出:[]

示例4

  • 输入:a = [1, 2, 3], b = [1, 2, 3]
  • 输出:[3, 2, 1]

2.4代码

def solution(a, b):
    # write code here
    res = []
    n1 = len(a)
    n2 = len(b)
    i, j = 0, 0
    while i < n1 and j < n2:
        if a[i] > b[j]:
            j += 1
        elif a[i] < b[j]:
            i += 1
        else:
            res.append(a[i])
            i += 1
            j += 1
    # print(res)
    res.reverse()
    return res


if __name__ == '__main__':
    print(solution([1, 2, 3, 7], [2, 5, 7]) == [7, 2])
    print(solution([1, 4, 8, 10], [2, 4, 8, 10]) == [10, 8, 4])
    print(solution([3, 5, 9], [1, 4, 6]) == [])
    print(solution([1, 2, 3], [1, 2, 3]) == [3, 2, 1])

3.代码详解

1.初始化指针和结果列表

i, j = 0, 0
result = []

2.双指针遍历两个数组

while i < len(a) and j < len(b):
    if a[i] == b[j]:
        result.append(a[i])
        i += 1
        j += 1
    elif a[i] < b[j]:
        i += 1
    else:
        j += 1

3.反转结果列表

result.reverse()

4.返回结果

return result