1331. 数组序号转换
class Solution:
def arrayRankTransform(self, arr: List[int]) -> List[int]:
ans=sorted(list(set(arr)))
hashmap={}
for i,value in enumerate(ans):
hashmap[value]=i+1
return [ hashmap[j] for j in arr]
1185. 一周中的第几天
class Solution(object):
def dayOfTheWeek(self, day, month, year):
"""
:type day: int
:type month: int
:type year: int
:rtype: str
"""
total = 0
monthDateN = [31,28,31,30,31,30,31,31,30,31,30,31]
monthDateL = [31,29,31,30,31,30,31,31,30,31,30,31]
for i in range(1970, year):
if self.isLeapYear(i):
total += 366
else:
total += 365
if self.isLeapYear(year):
for i in range(1, month):
total += monthDateL[i - 1]
else:
for i in range(1, month):
total += monthDateN[i - 1]
total += day
weekday = ["Wednesday","Thursday", "Friday", "Saturday","Sunday", "Monday", "Tuesday"]
return weekday[total % 7]
def isLeapYear(self, year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
915. 分割数组
该题需要左边的元素均小于等于右边的元素,所以重点是找到两个数组的分界点, 只要左边数组的最大值元素小于右边所有数组元素即可,因此从左至右遍历整个数组,创建两个变量保存左数组的最大值和当前遍历过所有数组的最大值,
如果当前遍历元素小于左边数组的最大值,则表示该元素以及之前所有元素属于左边数组,需要将分界点移至当前元素,同时将此元素之前所有元素的最大值赋给左数组最大值,直至遍历结束、
如果当前元素大于左边数组最大值,说明该元素目前可以作为右边数组,不需要移动分界点,只需要更新当前最大值即可
leftMax表示左侧最大值,curMax表示当前最大值,index用于标记左右分割的下标(即左子数组的结束下标)
遍历数组,当leftMax小于当前元素时则更新curMax,当leftMax大于当前元素时则更新边界下标index,并将当前leftMax更新为curMax。根据题意,当leftMax等于当前元素时无需更新左子数组(要求左子数组尽可能小)
class Solution:
def partitionDisjoint(self, A: List[int]) -> int:
leftmax,curmax=A[0],A[0]
idx=0
for i in range(1,len(A)):
if A[i]<leftmax:
idx=i
leftmax=curmax
elif A[i]>leftmax:
curmax=max(A[i],curmax)
return idx+1
914. 卡牌分组
所有卡牌中存在数字出现次数的公约数>=2才满足条件
reduce() 函数会对参数序列中元素进行累积。
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
reduce(function, iterable[, initializer])
from fractions import gcd
class Solution:
def hasGroupsSizeX(self, deck: List[int]) -> bool:
ans=Counter(deck).values()
return reduce(gcd,ans)>=2
283. 移动零
遇到不为0的元素就交换到数组前面,当前慢指针所指元素一定不为0,所以慢指针后移
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
i,j=0,0
for i in range(len(nums)):
if nums[i]!=0:
nums[i],nums[j]=nums[j],nums[i]
j+=1
138. 复制带随机指针的链表
我们只需要遍历整个图并拷贝它。拷贝的意思是每当遇到一个新的未访问过的节点,你都需要创造一个新的节点。
先把循环一遍,把所有节点都先new出来。next、random先留空。
如果要给一个新的node连接next,那么这个新node.next必须也应该是一个new出来的node,
因为旧node.next如果是一个节点的话,那么旧node.next肯定也是在map的keys里。
不能写作 lookup[node].next = lookup[node.next] ,因为如果node.next为空,这里就会报错了,
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
if not head:
return
lookup={}
cur=head
while cur:
lookup[cur]=Node(cur.val,None,None)
cur=cur.next
node=head
while node:
lookup[node].next=lookup.get(node.next)
lookup[node].random=lookup.get(node.random)
node=node.next
return lookup[head]
面试题 16.24. 数对和
哈希表存数字出现次数
class Solution:
def pairSums(self, nums: List[int], target: int) -> List[List[int]]:
match=defaultdict(int)
res=[]
for num in nums:
if match[target-num]>0:
res.append([num,target-num])
match[target-num]-=1
else:
match[num]+=1
return res
双指针
class Solution:
def pairSums(self, nums: List[int], target: int) -> List[List[int]]:
res=[]
nums.sort()
i,j=0,len(nums)-1
while i<j:
if nums[i]+nums[j]<target:
i+=1
elif nums[i]+nums[j]>target:
j-=1
elif nums[i]+nums[j]==target:
res.append([nums[i],nums[j]])
i+=1
j-=1
return res
1365. 有多少小于当前数字的数字
class Solution:
def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
ans=sorted(nums)
res=[]
for num in nums:
res.append(ans.index(num))
return res
330. 按要求补齐数组
设置一个当前数字最大覆盖范围cur_num,遍历nums,如果当前数值小于等于cur_num+1,表示覆盖范围可以向前扩展,如果不是,那么数字cur_num+1 不能被覆盖,这时候就需要新增这个数字,同时向后扩展覆盖范围,直到可以覆盖的范围大于等于n截止
当数组中元素被遍历完还无法覆盖【1,n】,那么逐个添加元素
必须要用cur_num+1,因为cur_num已经被覆盖了,如果当前元素大于cur_num+1,添加上当前元素之后,依然得不到cur_num+1,所以要把cur_num+1添加进去
class Solution:
def minPatches(self, nums: List[int], n: int) -> int:
res=0
cur_num=0
pos=0
while cur_num<n:
if pos<len(nums):
#cur_num+1能够被覆盖,扩大覆盖范围
if nums[pos]<=cur_num+1:
cur_num+=nums[pos]
pos+=1
else:
#cur_num+1不能被覆盖,添加该值
res+=1
cur_num+=cur_num+1
else:
res+=1
cur_num+=cur_num+1
return res
135. 分发糖果
先找从左到右满足最少的糖果,再找从右到左的,最后取两边都满足的值(就是最大值)。
class Solution:
def candy(self, ratings: List[int]) -> int:
res=0
leftcandy=[1]*len(ratings)
rightcandy=[1]*len(ratings)
for i in range(1,len(ratings)):
if ratings[i]>ratings[i-1]:
leftcandy[i]=leftcandy[i-1]+1
for i in range(len(ratings)-2,-1,-1):
if ratings[i]>ratings[i+1]:
rightcandy[i]=rightcandy[i+1]+1
for i in range(len(ratings)):
res+=max(leftcandy[i],rightcandy[i])
return res