记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
二分查找
1.两层二分
2.一层二分
排序后后面的引用次数大于当前
citations[mid]==n-mid 及当前的引用次数 == 大于等于当前引用次数的文章数
def hIndex(self, citations):
"""
:type citations: List[int]
:rtype: int
"""
if not citations:
return 0
n = min(len(citations),max(citations))
def check(num):
l,r = 0,len(citations)-1
while l<=r:
mid = (l+r)>>1
if citations[mid]>=num:
r = mid-1
else:
l = mid+1
if len(citations)-r-1>=num:
return True
return False
l,r = 0,n
ans = 0
while l<=r:
mid = (l+r)>>1
if check(mid):
ans = mid
l = mid+1
else:
r = mid-1
return ans
def hIndex2(citations):
"""
:type citations: List[int]
:rtype: int
"""
n = len(citations)
l,r = 0,n-1
while l<=r:
mid = (l+r)>>1
if citations[mid]==n-mid:
return n-mid
elif citations[mid]<n-mid:
l = mid+1
else:
r = mid-1
return n-l
1.二分 归并
保留每个建筑的左上角和右下角坐标
hl,hr分别代表左/右部分坐标中 当前考虑的建筑高度
locl,locr分别代表左/右部分中第几个坐标
合并:
首先考虑坐标x轴 先考虑x数值小的坐标 假设为左半部分(x0,y0) 右半部分当前坐标(x1,y1)
- 如果该坐标高度y0大于另一边当前建筑高度hr 说明这个坐标没有包含在建筑中 可以加入ret
- 如果该坐标高度y0小于另一边当前建筑高度hr 说明这个坐标在建筑中
- 如果当前建筑高度hl大于另一边当前建筑高度hr 说明这个坐标(x0,hr)是一个拐点 加入ret
- 如果当前建筑高度hl小于等于另一边当前刚度hr 说明这个坐标彻底在建筑内 无需显示
- 如果该坐标x0与x1相同 两点在同一个垂直线上
- 找到两个坐标较大的y数值max(y0,y1) 并且这个y不等于max(hl,hr)
如果等于 说明在同一个水平线上 不加入点
- 加入y数值较大的那个点
def getSkyline(buildings):
"""
:type buildings: List[List[int]]
:rtype: List[List[int]]
"""
def segment(l,r):
if l==r:
return [[buildings[l][0],buildings[l][2]],[buildings[l][1],0]]
mid = l+(r-l)//2
left = segment(l,mid)
right = segment(mid+1,r)
locl,locr=0,0
hl,hr=0,0
ret =[]
while locl<len(left) or locr<len(right):
if locl>=len(left):
ret.append(right[locr])
locr+=1
elif locr>=len(right):
ret.append(left[locl])
locl+=1
else:
if left[locl][0]<right[locr][0]:
if left[locl][1]>hr:
ret.append(left[locl])
elif hl>hr:
ret.append([left[locl][0],hr])
hl=left[locl][1]
locl+=1
elif left[locl][0]>right[locr][0]:
if right[locr][1]>hl:
ret.append(right[locr])
elif hr>hl:
ret.append([right[locr][0],hl])
hr=right[locr][1]
locr+=1
else:
if left[locl][1]>=right[locr][1] and left[locl][1]!=max(hr,hl):
ret.append(left[locl])
elif left[locl][1]<=right[locr][1] and right[locr][1]!=max(hr,hl):
ret.append(right[locr])
hl=left[locl][1]
hr=right[locr][1]
locl+=1
locr+=1
return ret
return segment(0,len(buildings)-1)
1.diff 记录每个位置差值绝对值
total 差值绝对值总和 如果一开始total就为0不需要交换直接返回
diffv 代表我们希望能够从total中减少的数值 越大越好
但最大不会超过abs(nums1[i]-nums2[i])
diffmap 记录每一个差值对应的位置
difflist 从大到小排序好的每一个差值
从difflist中取出当前最大的差值
从diffmap获取该差值的位置 loc
tmp为减小diffv差值 nums2 与 nums1中的数需要有的差值
可以比nums2大或者小 查看 nums2+/-tmp 这个数是否在nums1中存在
如果存在那么总和可以减小diffv
如果不存在 那么这个位置考虑diffv-1是否存在 将diffv-1放入考虑对列中
2.二分
对于位置i 查找nums2[i] 能够在nums1能找到的最接近的数
def minAbsoluteSumDiff(nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: int
"""
mod = 10**9+7
n = len(nums1)
snum = set(nums1)
diff = [abs(nums1[i]-nums2[i]) for i in range(n)]
total = sum(diff)
if total==0:
return total
from collections import defaultdict
diffmap = defaultdict(list)
for i in range(n):
diffmap[diff[i]].append(i)
difflist = list(set(diff))
difflist.sort(reverse=True)
while difflist:
diffv = difflist.pop(0)
if diffv==0:
break
l = diffmap[diffv]
for loc in l:
oriv = nums2[loc]
tmp = abs(nums1[loc]-nums2[loc]) - diffv
if oriv + tmp in snum or oriv-tmp in snum:
total -= diffv
return total % mod
diffmap[diffv-1].append(loc)
if not difflist or diffv-1 > difflist[0]:
difflist = [diffv-1]+difflist
return total %mod
def minAbsoluteSumDiff2(nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: int
"""
mod = 10**9+7
import bisect
n = len(nums1)
snums1 = sorted(nums1)
total = 0
maxv = 0
for i in range(n):
v1,v2 = nums1[i],nums2[i]
diff = abs(v1-v2)
total += diff
if diff==0:
continue
loc = bisect.bisect_left(snums1,v2)
if loc<n:
maxv = max(maxv,diff-abs(snums1[loc]-v2))
if loc>0:
maxv = max(maxv,diff-abs(snums1[loc-1]-v2))
return (total-maxv)%mod
从小到大排序
第一个位置必定是1 之后如果不满足条件 则变为前一个位置+1 尽可能小
def maximumElementAfterDecrementingAndRearranging(arr):
"""
:type arr: List[int]
:rtype: int
"""
arr.sort()
n = len(arr)
arr[0]=1
for i in range(1,n):
if arr[i]-arr[i-1]>1:
arr[i] = arr[i-1]+1
return arr[n-1]
二分 搜索
def search(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if target not in nums:
return 0
n = len(nums)
def func(l,r):
print(l,r)
if l>r:
return 0
if l==r:
if nums[l]==target:
return 1
else:
return 0
if nums[l]==target and nums[r]==target:
return r-l+1
mid = l+(r-l)//2
print(l,r,mid)
if nums[mid]==target:
return 1+func(l,mid-1) + func(mid+1,r)
else:
if nums[mid]<target:
return func(mid+1,r)
else:
return func(l,mid+1)
return func(0,n-1)
当前和大于0时可以继续往下加 否则从0开始重新计算
def maxSubArray(nums):
"""
:type nums: List[int]
:rtype: int
"""
ret=max(nums)
num =0
for i in nums:
if num+i>0:
num+=i
ret=max(ret,num)
else:
num=0
return ret
每个单词根据字母出现次数进行标签 变位词标签相同
统计每一类标签词语个数
def groupAnagrams(strs):
"""
:type strs: List[str]
:rtype: List[List[str]]
"""
from collections import defaultdict
def check(word):
m = defaultdict(int)
for c in word:
m[c]+=1
keys = list(m.keys())
keys.sort()
h = ""
for k in keys:
h+=k
h+=str(m[k])
return h
loc = 0
ans = []
m = {}
for s in strs:
h = check(s)
if h in m:
ans[m[h]].append(s)
else:
m[h]=loc
loc+=1
ans.append([s])
return ans