记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
1.用户x不会对大于自己岁数的y发送好友请求
统计各个年龄各有多少人 存入m
将年龄从下到大排列 生成前缀和数组
统计每个年龄会加好友的区间 二分
2.因为年纪范围知道 计数排序 前缀和
def numFriendRequests1(ages):
"""
:type ages: List[int]
:rtype: int
"""
from collections import defaultdict
m = defaultdict(int)
for age in ages:
m[age]+=1
ageList = list(m.keys())
ageList.sort()
presum = [0,m[ageList[0]]]
for i in range(1,len(ageList)):
presum.append(presum[i]+m[ageList[i]])
ans = 0
for loc,age in enumerate(ageList):
num = m[age]
minage = age*1.0/2+7 #大于minage
if minage<age:
ans += num*(num-1)
l,r = 0,loc-1
while l<=r:
mid = (l+r)//2
if ageList[mid]>minage:
r = mid-1
else:
l = mid+1
if l>=0 and loc>=0:
ans += (presum[loc]-presum[l])*num
return ans
def numFriendRequests(ages):
"""
:type ages: List[int]
:rtype: int
"""
total = [0]*121
for age in ages:
total[age]+=1
presum = [0]*121
for i in range(1,121):
presum[i] = presum[i-1]+total[i]
ans = 0
for age in range(15,121):
if total[age]>0:
minage = int(age/2+8)-1
ans += total[age]*(presum[age]-presum[minage]-1)
return ans
1.要包含合成词 必须要含有三个以上的单词
合成词肯定是若干个短的词拼接而成 所以我们可以先从短的词开始分析
使用一个set来存储已经考虑过的list中较短的单词 当以后再次需要分析这个单词时可直接返回True
使用set可以减少用in查找时的耗时
超时
2.字典树
将词组从短到长排序
判断一个单词是否是连接词 在字典树中DFS
def findAllConcatenatedWordsInADict1(words):
"""
:type words: List[str]
:rtype: List[str]
"""
ret = []
if len(words)<3:
return ret
words.sort(key=lambda x:len(x))
exist_dict = set()
def check(w):
if w in exist_dict:
return True
for i in range(len(w)-1,0,-1):
if w[:i] in exist_dict and check(w[i:]):
return True
return False
for w in words:
if check(w):
ret.append(w)
exist_dict.add(w)
return ret
def findAllConcatenatedWordsInADict(words):
"""
:type words: List[str]
:rtype: List[str]
"""
trie = {}
def add(word):
node = trie
for c in word:
if c in node:
node = node[c]
else:
node[c] = {}
node = node[c]
node['end']=1
def dfs(word):
if word=="":
return True
node = trie
for i,c in enumerate(word):
if c in node:
tmp = node[c]
if 'end' in tmp and dfs(word[i+1:]):
return True
node = node[c]
else:
return False
ret = []
if len(words)<3:
return ret
words.sort(key=lambda x:len(x))
for word in words:
if word =="":
continue
if dfs(word):
ret.append(word)
else:
add(word)
return ret
1.普通四重枚举
2.a+b+c=d
从后往前枚举c位置 map存储d可能的数值出现次数
def countQuadruplets1(nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
ans = 0
for a in range(n-3):
for b in range(a+1,n-2):
for c in range(b+1,n-1):
for d in range(c+1,n):
if nums[a]+nums[b]+nums[c]==nums[d]:
ans +=1
return ans
def countQuadruplets(nums):
"""
:type nums: List[int]
:rtype: int
"""
from collections import defaultdict
n = len(nums)
m = defaultdict(int)
ans = 0
for c in range(n-2,1,-1):
m[nums[c+1]]+=1
for a in range(c-1):
for b in range(a+1,c):
s = nums[a]+nums[b]+nums[c]
if s in m:
ans += m[s]
return ans
每一组有groupSize张牌 所以hand的个数必定需要被其整除
如果无法整除必定false
map统计每种牌的张数
使用最小堆存放出现的所有牌面值
从最小堆中取出个数不为0的最小牌面
依次增大连续groupSize张
从map中将相应的牌数量减一
如果出现中途某一牌面无牌 则说明false
小优化:
如果某一牌面数量k每组数量已经大于剩余的数量
说明无法组成完整的k组 返回false
例如 每组数量为4 剩余牌8张为 1,1,1,2,2,3,3,4,
取最小值1 此时1的数量为2 34>8 必定无法组成三组
def isNStraightHand(hand, groupSize):
"""
:type hand: List[int]
:type groupSize: int
:rtype: bool
"""
from collections import defaultdict
import heapq
l = []
heapq.heapify(l)
n = len(hand)
if n%groupSize!=0:
return False
if groupSize==1:
return True
m = defaultdict(int)
for num in hand:
m[num]+=1
if m[num]==1:
heapq.heappush(l,num)
while n>0:
start = l[0]
while m[start]==0:
heapq.heappop(l)
start = l[0]
for i in range(start,start+groupSize):
num = m[i]
if num==0 or groupSize*num>n:
return False
m[i]-=1
n-=groupSize
return True
求出Num的2次方根sqrt
从2到sqrt判断是否是num的因数 将不同的因数累加
def checkPerfectNumber(num):
"""
:type num: int
:rtype: bool
"""
if num==1:
return False
sqrt = int(num**(1/2))+1
s = 1
for i in range(2,sqrt):
if num%i==0:
s += i
if num//i!=i:
s += num//i
if s>num:
return False
return s==num
判断个数是否等于m*n个
共m行 依次取n个
def construct2DArray(original, m, n):
"""
:type original: List[int]
:type m: int
:type n: int
:rtype: List[List[int]]
"""
ans = []
if len(original)!=m*n:
return ans
for i in range(m):
ans.append(original[i*n:i*n+n])
return ans
每次去除一半
如果是第k轮 间隔step = 2^k
k为偶数 从左到右
此时开头位置x数值必定改变 为x+step
k为奇数 从右到左
如果个数为奇数 开头位置变为x+step
如果个数为偶数 开头位置保留
def lastRemaining(n):
"""
:type n: int
:rtype: int
"""
start = 1
step = 1
k = 0
num = n
while num>1:
if k%2==0:
start += step
elif num%2==1:
start +=step
k+=1
num >>=1
step<<=1
return start