记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
-
-
- [7/27 1464. 数组中两元素的最大乘积](#7/27 1464. 数组中两元素的最大乘积)
- [7/28 3517. 最小回文排列 I](#7/28 3517. 最小回文排列 I)
- [7/29 3518. 最小回文排列 II](#7/29 3518. 最小回文排列 II)
- [7/30 3014. 输入单词需要的最少按键次数 I](#7/30 3014. 输入单词需要的最少按键次数 I)
- [7/31 3016. 输入单词需要的最少按键次数 II](#7/31 3016. 输入单词需要的最少按键次数 II)
- [8/1 486. 预测赢家](#8/1 486. 预测赢家)
- 8/2
-
7/27 1464. 数组中两元素的最大乘积
排序 最大两数乘积
python
def maxProduct(nums):
"""
:type nums: List[int]
:rtype: int
"""
nums.sort()
return (nums[-1]-1)*(nums[-2]-1)
7/28 3517. 最小回文排列 I
如果长度为n 将前n//2个字符从小到大排序 即可
python
def smallestPalindrome(s):
"""
:type s: str
:rtype: str
"""
n = len(s)
l = sorted(s[:n//2])
if n % 2 == 0:
return ''.join(l) + ''.join(l[::-1])
else:
return ''.join(l) + s[n//2] + ''.join(l[::-1])
7/29 3518. 最小回文排列 II
回文由前半段唯一决定,后半段镜像即可,奇数长度时中间字符固定。
先统计每种字符出现次数,取一半作为前半段可用字符。
按字典序逐位构造前半段:尝试放某个字符后,计算剩余字符的不同排列数;若不少于 k,则选定该字符,否则从 k 中减去这些排列并尝试下一个字符。
排列数用多重组合公式计算,超过 k 的上界时截断,避免大整数拖慢速度。
若总排列数小于 k,返回空串。
python
def smallestPalindrome(s, k):
"""
:type s: str
:type k: int
:rtype: str
"""
MAX = 10**6 + 1
cnt = [0] * 26
for c in s:
cnt[ord(c) - 97] += 1
half = [0] * 26
mid = ""
for i in range(26):
if cnt[i] % 2:
mid = chr(i + 97)
half[i] = cnt[i] // 2
def nCk(n, r):
if r < 0 or r > n:
return 0
r = min(r, n - r)
res = 1
for i in range(1, r + 1):
res = res * (n - i + 1) // i
if res >= MAX:
return MAX
return res
def arrangements(freq):
total = sum(freq)
res = 1
for f in freq:
if f == 0:
continue
res *= nCk(total, f)
if res >= MAX:
return MAX
total -= f
return res
if arrangements(half) < k:
return ""
left = []
length = sum(half)
for _ in range(length):
for i in range(26):
if half[i] == 0:
continue
half[i] -= 1
ways = arrangements(half)
if ways >= k:
left.append(chr(i + 97))
break
k -= ways
half[i] += 1
return "".join(left) + mid + "".join(reversed(left))
7/30 3014. 输入单词需要的最少按键次数 I
统计每个字母出现的次数 排序
次数多的放在键的前面 有八个可以放第一个 第九个就需要按两次才能出现一次
python
def minimumPushes(word):
"""
:type word: str
:rtype: int
"""
cnt = [0] * 26
for c in word:
cnt[ord(c) - 97] += 1
cnt.sort(reverse=True)
res = 0
num=0
for i in range(26):
if cnt[i] > 0:
res += cnt[i] * (num//8+1)
num += 1
return res
7/31 3016. 输入单词需要的最少按键次数 II
统计每个字母出现的次数 排序
次数多的放在键的前面 有八个可以放第一个 第九个就需要按两次才能出现一次
python
def minimumPushes(word):
"""
:type word: str
:rtype: int
"""
cnt = [0] * 26
for c in word:
cnt[ord(c) - 97] += 1
cnt.sort(reverse=True)
res = 0
num=0
for i in range(26):
if cnt[i] > 0:
res += cnt[i] * (num//8+1)
num += 1
return res
8/1 486. 预测赢家
dp
dpij代表从i到j范围内能取到的比对方打的最大值
dpii = numsi
dpij 可以取numsi 或者numsj
numsi取了之后对方的最大值为dpi+1j
numsj取了之后对方的最大值为dpij-1
比较这两个哪个差值大 用哪个
python
def PredictTheWinner(nums):
"""
:type nums: List[int]
:rtype: bool
"""
n = len(nums)
dp = [[0] * n for _ in range(n)]
for i,num in enumerate(nums):
dp[i][i]=num
for i in range(n-2,-1,-1):
for j in range(i+1,n):
dp[i][j] = max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1])
return dp[0][n-1]>=0
8/2
python