LeetCode 每日一题 2021/7/12-2021/7/18

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步




7/12 275. H-Index II H 指数 II

二分查找
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

7/13 218. The Skyline Problem 天际线问题

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)

7/14 1818. Minimum Absolute Sum Difference 绝对差值和

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

7/15 1846. Maximum Element After Decreasing and Rearranging 减小和重新排列数组后的最大元素

从小到大排序
第一个位置必定是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]

7/16 剑指 Offer 53 - I. 在排序数组中查找数字 I

二分 搜索


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)
        

7/17 剑指 Offer 42. 连续子数组的最大和

当前和大于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

7/18 面试题 10.02. 变位词组

每个单词根据字母出现次数进行标签 变位词标签相同
统计每一类标签词语个数

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值