1.1 简单 用时5min
2351. 第一个出现两次的字母
注意!!!python创建空集合只能用set(),如果用{}创建的是字典。
class Solution:
def repeatedCharacter(self, s: str) -> str:
res = set()
for x in s:
if x not in res:
res.add(x)
else:
return x
return ""
1.2 中等 用时x 想了半小时没想出来
1801. 积压订单中的订单总数***
想了很久没有想出合适复杂度的方法。看官解使用了优先队列。按照题意应该将sell由小到大排序,buy由大到小排序。
先复习一下优先队列的知识:(待填坑)
在python中可以使用堆来实现,操作有heappush和heappop,由于python的堆是小根堆,所以buy入队时将元素取负数,这也是常用的操作。
时间复杂度为O(nlogn),其中logn为每次处理优先队列的时间复杂度。空间复杂度为O(n)
class Solution:
def getNumberOfBacklogOrders(self, orders: List[List[int]]) -> int:
MOD = 10 ** 9 + 7
buyOrders, sellOrders = [], []
for price, amount, type in orders:
if type == 0:
while amount and sellOrders and sellOrders[0][0] <= price:
if sellOrders[0][1] > amount:
sellOrders[0][1] -= amount
amount = 0
break
amount -= heappop(sellOrders)[1]
if amount:
heappush(buyOrders, [-price, amount])
else:
while amount and buyOrders and -buyOrders[0][0] >= price:
if buyOrders[0][1] > amount:
buyOrders[0][1] -= amount
amount = 0
break
amount -= heappop(buyOrders)[1]
if amount:
heappush(sellOrders, [price, amount])
return (sum(x for _, x in buyOrders) + sum(x for _, x in sellOrders)) % MOD
作者:力扣官方题解
链接:https://leetcode.cn/problems/number-of-orders-in-the-backlog/solutions/2039856/ji-ya-ding-dan-zhong-de-ding-dan-zong-sh-6g22/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1.3 简单 用时 10min
2042. 检查句子中的数字是否递增
比较简单,但是时空复杂度都是O(n),按照官解那种一个一个字符遍历可以把空间复杂度压缩到O(1)。
class Solution:
def areNumbersAscending(self, s: str) -> bool:
res = s.split(' ')
num = 0
for x in res:
if x.isdigit():
if int(x) <= num: return False
else:num = int(x)
return True
1.4 中等 用时2h
1802. 有界数组中指定下标处的最大值
通过将和划分成index的左边、index的右边、index,直接推出了和的表达式(由于我到处缺一少一错了四五次),于是就变成了解方程的查找问题,一开始用for循环超时了,想到用二分查找,第一反应是递归,然后递归层数太多过不了,改用while循环,通过。当然,这是个一元二次方程,也可以通过分情况去公式求解,即(没错我忘记了公式所以没用)。
反思:每次直接上手写,一瞬间想到更快的解法但是懒得想和写。
class Solution:
def maxValue(self, n: int, index: int, maxSum: int) -> int:
maxSum = maxSum - n
left, right = 0, maxSum
while left
看题解发现还可以用贪心算法加二分查找的方法。 下面贴上官方题解。
class Solution:
def maxValue(self, n: int, index: int, maxSum: int) -> int:
left, right = 1, maxSum
while left < right:
mid = (left + right + 1) // 2
if self.valid(mid, n, index, maxSum):
left = mid
else:
right = mid - 1
return left
def valid(self, mid: int, n: int, index: int, maxSum: int) -> bool:
left = index
right = n - index - 1
return mid + self.cal(mid, left) + self.cal(mid, right) <= maxSum
def cal(self, big: int, length: int) -> int:
if length + 1 < big:
small = big - length
return ((big - 1 + small) * length) // 2
else:
ones = length - (big - 1)
return (big - 1 + 1) * (big - 1) // 2 + ones
作者:力扣官方题解
链接:https://leetcode.cn/problems/maximum-value-at-a-given-index-in-a-bounded-array/solutions/2042360/you-jie-shu-zu-zhong-zhi-ding-xia-biao-c-aav4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1.5 困难 不会
字典树
1.6 简单 10min
2180. 统计各位数字之和为偶数的整数个数
class Solution:
def countEven(self, num: int) -> int:
s = 0
n = num
while n:
s += n%10
n = n//10
if s % 2 == 0:
return num//2
else:
return (num-1)//2
1.7 中等
1658. 将 x 减到 0 的最小操作数
滑动窗口! 竟然忘记了这个解法;注意外层的for循环,因为要最小的和为x的长度,所以如果少一层循环结果可能不是最小。
class Solution:
def minOperations(self, nums: List[int], x: int) -> int:
if len(nums)==1:
return 1 if nums[0]==x else -1
s = sum(nums)
total = len(nums)+1
right = 0
for left in range(-1,len(nums)-1):
if left!=-1: s+=nums[left]
while rightx:
s-=nums[right]
right += 1
if s==x:
total = min(len(nums)-right+left+1, total)
return total if total
1.8 简单 略
1.9 中等 30min
1806. 还原排列的最少操作步数
class Solution:
def reinitializePermutation(self, n: int) -> int:
perm = [i for i in range(n)]
watch = [i for i in range(n)]
arr = [0 for _ in range(n)]
count = 0
while arr!=watch:
for i in range(n):
if i%2 == 0:
arr[i] = perm[i//2]
else:
arr[i] = perm[n//2 + (i-1)//2]
perm = arr[:]
count += 1
if perm==watch:
return count
return -1
1.10 困难 不会
753. 破解保险箱
先取学习一下欧拉回路/通路
Hierholzer 算法如下:
我们从节点 uuu 开始,任意地经过还未经过的边,直到我们「无路可走」。此时我们一定回到了节点 uuu,这是因为所有节点的入度和出度都相等。
回到节点 uuu 之后,我们得到了一条从 uuu 开始到 uuu 结束的回路,这条回路上仍然有些节点有未经过的出边。我么从某个这样的节点 vvv 开始,继续得到一条从 vvv 开始到 vvv 结束的回路,再嵌入之前的回路中
下面这个图非常帮助理解,来自力扣
这个图让我想起来数字电路,知识真是相通的啊,太妙了。
class Solution:
def crackSafe(self, n: int, k: int) -> str:
seen = set()
ans = list()
highest = 10 ** (n - 1)
def dfs(node: int):
for x in range(k):
nei = node * 10 + x
if nei not in seen:
seen.add(nei)
dfs(nei % highest)
ans.append(str(x))
dfs(0)
return "".join(ans) + "0" * (n - 1)
作者:力扣官方题解
链接:https://leetcode.cn/problems/cracking-the-safe/solutions/393529/po-jie-bao-xian-xiang-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1.11 简单
2283. 判断一个数的数字计数是否等于数位的值
注意一下数据类型就行,还有如果没有用Counter,注意出现次数0在字典中没有的情况。
class Solution:
def digitCount(self, num: str) -> bool:
h = Counter(num)
for idx, v in enumerate(num):
if h[str(idx)] != int(v):
return False
return True
1.12 中等
1807. 替换字符串中的括号内容
看着答案提醒才做出来,注意不在括号里的要怎么处理。我一开始是想直接替换,结果python字符串是不可变的,然后试着用切片的方法,但是忽略了修改字符串后原来记下的括号的索引也变了!!所以想着改字符串是行不通的,还是得数组。
class Solution:
import re
def evaluate(self, s: str, knowledge: List[List[str]]) -> str:
d = dict(knowledge)
n = len(s)
i = 0
res = []
while i
1.13 简单
2287. 重排字符形成目标字符串
自己只对s做了哈希表,然后一遍遍遍历target,我真傻555。
# 我的
class Solution:
def rearrangeCharacters(self, s: str, target: str) -> int:
dic = Counter(s)
res = 0
flag = 1
while flag:
for i in target:
if i in dic and dic[i]>0:
dic[i]-=1
else:
flag = 0
break
if flag: res+=1
return res
# 官解下面一个人的一行代码
class Solution:
def rearrangeCharacters(self, s: str, target: str) -> int:
return min(Counter(s)[i] // v for i, v in Counter(target).items())