题目1:146.字符串首尾相同子序列计数
问题描述
小M拿到了一个仅由小写字母组成的字符串,她想知道在这个字符串中,有多少个子序列的首尾字符相同。子序列的定义是:从原字符串中按原顺序取出若干字符(可以不连续)组成的新字符串。
例如,对于字符串 "arcaea",其子序列包括 "aca", "ara", "aaa" 等,这些子序列的首尾字符都是相同的。
你需要计算满足这一条件的子序列数量,并输出对 998244353 取模的结果。
测试样例
输入:s = "arcaea"
输出:28
解析思路
对于某一字符作为子序列的首字符,只有往后遍历所有字符才能找全首尾字符相同的子序列,因此仍然考虑使用双循环解决问题,外层循环枚举子序列首字符,内层循环枚举子序列尾字符。
当枚举到首尾字符相同时,该首尾两字符之间所能组成的所有子序列都满足条件,因此问题转换为两字符之间有多少种子序列组合。假设首尾两字符之间一共有n个字符(不包含首尾字符),则所有组合的可能为。这同样包含了首尾两字符间没有其他字符的情况,首尾两字符自己组成的子序列也符合要求。
因此,在每次内循环开始时,同时统计目前首尾字符之间的字符数量n,当枚举到首尾字符相同时,让最终答案加上即可。
完整代码如下:
def solution(s: str) -> int:
ans = len(s)
for i in range(len(s)):
sub_len = 0
for j in range(i+1, len(s)):
if s[i] == s[j]:
ans += 2 ** sub_len
sub_len += 1
return ans
题目2:119.游戏队友搜索
问题描述
在一款多人游戏中,每局比赛需要多个玩家参与。如果发现两名玩家至少一起玩过两局比赛,则可以认为这两名玩家互为队友。现在你有一份玩家(通过玩家ID标识)和比赛局次(通过比赛ID标识)的历史记录表,目标是帮助某位指定玩家找到所有符合条件的队友。
测试样例
输入:id = 1, num = 10, array = [[1,1], [1,2], [1,3], [2,1], [2,4], [3,2], [4,1], [4,2], [5,2], [5,3]]
输出:[4, 5]
解析思路
这题主要分为3步,一是先遍历一遍记录表找到指定玩家参与过的所有比赛局次,二是再遍历一遍记录表找到相关比赛局次的所有队友并记录同局次数,三是从所有队友中找到符合条件的队友ID。
-
遍历一遍历史记录表,用数组
match_id_list储存指定玩家参与过的比赛ID。 -
由于不同局次的队友可能会用重复,因此考虑使用字典
history_teammates来储存队友ID和同局次数。遍历一遍历史记录表,若是该指定玩家的ID则continue;若是不同玩家且对局ID在match_id_list中,则判断字典中有无其记录:若没有,以其ID为键、1为值进行初始化,若有,值加1,以此记录该玩家和指定玩家同局的次数。 -
遍历
history_teammates中所有的键,所有值大于等于2的即为符合条件的队友。
完整代码如下:
def solution(id, num, array):
match_id_list = []
for i in range(num):
if array[i][0] == id:
match_id_list.append(array[i][1])
history_teammates = {}
for i in range(num):
if array[i][0] == id:
continue
if array[i][1] in match_id_list:
if array[i][0] not in history_teammates:
history_teammates[array[i][0]] = 1
else:
history_teammates[array[i][0]] += 1
eligible = []
for key in history_teammates:
if history_teammates[key] >= 2:
eligible.append(key)
eligible.sort()
return eligible