「力扣挑战赛」心算项目的挑战比赛中,要求选手从 N
张卡牌中选出 cnt
张卡牌,若这 cnt
张卡牌数字总和为偶数,则选手成绩「有效」且得分为 cnt
张卡牌数字总和。 给定数组 cards
和 cnt
,其中 cards[i]
表示第 i
张卡牌上的数字。 请帮参赛选手计算最大的有效得分。若不存在获取有效得分的卡牌方案,则返回 0。
示例 1:
输入:
cards = [1,2,8,9], cnt = 3
输出:
18
解释:选择数字为 1、8、9 的这三张卡牌,此时可获得最大的有效得分 1+8+9=18。
示例 2:
输入:
cards = [3,3,1], cnt = 1
输出:
0
解释:不存在获取有效得分的卡牌方案。
提示:
1 <= cnt <= cards.length <= 10^5
1 <= cards[i] <= 1000
思路:
先找 happy path,看前 cnt 大的牌和是不是偶数, 如果是那么很好直接返回它。
如果和是奇数,就说明我们需要换牌了,换牌策略有两种:
1. 把已经拿走的牌里最小的偶数,换成自由牌里最大的奇数。
2. 把已经拿走的牌里最小的奇数,换成自由牌里最小的偶数。
时间复杂度:O(NlogN)
空间复杂度:O(1)
class Solution:
def maximumScore(self, cards: List[int], cnt: int) -> int:
cards.sort(reverse = True)
s = sum(cards[:cnt])
if s % 2 == 0:
return s
# find the smallest_even in the left, swap it with largest_odd in the right
# find the smallest_odd in the left, swap it with the largest_odd in the right
smallest_even = smallest_odd = None
for c in cards[:cnt][::-1]:
if smallest_even is None and c % 2 == 0:
smallest_even = c
elif smallest_odd is None and c % 2 == 1:
smallest_odd = c
if smallest_even and smallest_odd:
break
largest_odd = largest_even = None
for c in cards[cnt:]:
if largest_even is None and c % 2 == 0:
largest_even = c
elif largest_odd is None and c % 2 == 1:
largest_odd = c
if largest_even and largest_odd:
break
res = 0
if largest_even and smallest_odd:
res = max(res, s - smallest_odd + largest_even)
if largest_odd and smallest_even:
res = max(res, s - smallest_even + largest_odd)
return res