记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
1/10 306. 累加数
使用add函数将两个字符串类型的数相加
遍历开头两个数的可能性fst,snd
开头不能为0 除非只有0
def isAdditiveNumber(num):
"""
:type num: str
:rtype: bool
"""
def add(a,b):#len(a)<len(b)
if len(a)>len(b):
a,b = b,a
la = list(a)
lb = list(b)
ans = []
jin = 0
for i in range(1,len(la)+1):
v = int(la[-i])+int(lb[-i])+jin
jin = 0
if v>9:
v %=10
jin = 1
ans = [str(v)]+ans
for j in range(len(la)+1,len(lb)+1):
v = int(lb[-j])+jin
jin = 0
if v>9:
v %=10
jin = 1
ans = [str(v)]+ans
if jin>0:
ans = [str(jin)]+ans
return "".join(ans)
n = len(num)
maxl = n//2
for i in range(1,maxl+1):
tmp = num
for j in range(1,(n-i)//2+1):
fst = tmp[:i]
snd = tmp[i:i+j]
if snd[0]=="0" and len(snd)>1:
continue
loc = i+j
while loc<n:
thd = add(fst,snd)
ln = len(thd)
if loc+ln==n and tmp[loc:loc+ln]==thd:
return True
elif loc+ln<n and tmp[loc:loc+ln]==thd:
fst,snd = snd,thd
loc = loc+ln
else:
break
return False
1/11 1036. 逃离大迷宫
判断两点是否能够连通可以使用BFS
但由于网格过于庞大 必定超时
看到封锁的方格最多只有200个
可以思考 有n个封锁的方格 最大能够封锁的面积为(n^2)/2 当n个方格为等腰直角三角形斜边时
如果一个点在封锁区内 那么它能够到达的面积<=最大封锁面积
如果一个点能够到达的面积大于最大封锁面积 那么这个点必定没有被封锁网格封锁住
判断起点终点是否被封锁住 在判断中途有个能已经相连
def isEscapePossible(blocked, source, target):
"""
:type blocked: List[List[int]]
:type source: List[int]
:type target: List[int]
:rtype: bool
"""
if len(blocked)==0:
return True
bset = set()
for x,y in blocked:
bset.add((x,y))
blen = len(blocked)
tsize = blen**2//2
def isOpen(start,end):
num = 1
mem = set()
mem.add((start[0],start[1]))
l = [start]
while l:
tmp = []
for x,y in l:
for i,j in [(1,0),(0,1),(-1,0),(0,-1)]:
newx,newy = x+i,y+j
if 0<=newx<10**6 and 0<=newy<10**6:
if (newx,newy) not in mem and (newx,newy) not in bset:
if newx==end[0] and newy==end[1]:
return True
num+=1
tmp.append((newx,newy))
mem.add((newx,newy))
if num>tsize:
return True
l = tmp[:]
return False
return isOpen(source,target) and isOpen(target,source)
1/12 334. 递增的三元子序列
类似LCS问题 最长上升子序列
因为只要找到三个 所以我们只需要两个变量 记录前两个数
fst,snd 单调递增 当找到大于snd的数时 则该数可以与前两个构成递增三元组
如果小于snd大于fst 则更新snd
如果小于fst 则更新fst
def increasingTriplet(nums):
"""
:type nums: List[int]
:rtype: bool
"""
if len(nums)<3:
return False
fst = nums[0]
snd = float("inf")
for i in range(1,len(nums)):
if nums[i]>snd:
return True
elif nums[i]>fst:
snd = nums[i]
else:
fst = nums[i]
return False
1/13 747. 至少是其他数字两倍的最大数
确定最大值 从头遍历记录最大值位置
判断所有值是否小于等于最大值一半
def dominantIndex(nums):
"""
:type nums: List[int]
:rtype: int
"""
target = max(nums)
ans = -1
for loc,num in enumerate(nums):
if num==target:
ans = loc
elif num<target and num*2>target:
return -1
return ans
1/14 373. 查找和最小的 K 对数字
每个数组最多涉及前K个数
先将nums1[0] + nums2[x] x=[0,k)
一共k个结果放入最小堆中
取当前最小值 numx1[i]+nums2[j] 将nums1[i+1]+nums2[j]放入堆中
def kSmallestPairs(nums1, nums2, k):
"""
:type nums1: List[int]
:type nums2: List[int]
:type k: int
:rtype: List[List[int]]
"""
import heapq
l = []
heapq.heapify(l)
len1 = min(len(nums1),k)
len2 = min(len(nums2),k)
for i in range(len2):
heapq.heappush(l,(nums1[0]+nums2[i],0,i))
ans = []
for _ in range(k):
if len(l)==0:
break
_,x,y = heapq.heappop(l)
ans.append([nums1[x],nums2[y]])
if x+1<len1:
for j in range(len2):
heapq.heappush(l,(nums1[x+1]+nums2[j],x+1,j))
return ans
1/15 1716. 计算力扣银行的钱
第一周存 1+2+…+7=28
第二周存 2+3+…+8=35
第i周存 i+(i+1)+…+(i+6) = 21+7i
共有i周 总数=21*i+(1+2+…+i)i//27
剩余天数 第一天为i+1块
def totalMoney(n):
"""
:type n: int
:rtype: int
"""
week = n//7
day = n%7
ans = 0
ans = 21*week+(1+week)*week*7//2
ans += (week+1+week+day)*day//2
return ans
1/16 382. 链表随机节点
水塘抽样算法
一次遍历每个节点 对于节点i 当前选他为答案的概率为1/i (1-1/i)的概率保持答案不变
对于节点i最终的可能性:
1/i*(1-1/(i+1))(1-1/(i+2))…(1-1/n)
= 1/i(i/i+1)(i+1/i+2)…*(n-1/n)
= 1/n
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
def __init__(self, head):
"""
:type head: Optional[ListNode]
"""
self.node = head
def getRandom(self):
"""
:rtype: int
"""
import random
node,ans,i = self.node,None,0
while node:
if random.randint(0,i)==0:
ans = node.val
node,i = node.next,i+1
return ans