LeetCode-贪心算法-Hard

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




44.wildcard-matching 通配符匹配

解题思路:1.
dp[0][0]=true
dp[i][j]表示s的前i个字符与p的前j个字符是否匹配
初始化p为* 与前面满足的状态一直
如果p[j-1]的位置为*:
1.p退一位满足 及代表空 dp[i][j-1]
2.s退一位满足 及
代表字符串 dp[i-1][j]
3.p,s各退一位满足 及代表这个字符 dp[i-1][j-1]
若p的位置不为
需同时满足:
1.p,s这个位置的字符相等 或者 p的位置为?
2.同时前一个位置需要满足条件 true
最终结果为dp[len(s)][len§] 此方法耗时较大

2.先遍历s i,j分别记录s,p的位置 start用来记录的位置 m用来记录用代替若干个字符后s的位置
如果s[i]p[j]或p[j]’?‘则这个位置满足 i,j同时+1
如果p[j]==’’ 记录的位置start 和s当前的位置m p的位置+1
如果 存在及start有位置的值 那么将p挪回到后的位置start+1 s的位置往后移i=m+1
若都不满足则返回失败
遍历完s后,查看p的位置j 略过*的位置
如果j已经在p的末尾则说明匹配成功

def isMatch(s, p):
    """
    :type s: str
    :type p: str
    :rtype: bool
    """
    dp = [[False for i in range(len(p)+1)] for j in range(len(s)+1)]
    dp[0][0]=True
     
    for i in range(1,len(p)+1):
        if p[i-1]=='*':
            dp[0][i] = dp[0][i-1]
    
    for i in range(1,len(s)+1):
        for j in range(1,len(p)+1):
            if p[j-1]=='*':
                dp[i][j] = dp[i-1][j] or dp[i][j-1] or dp[i-1][j-1]
            else:
                dp[i][j] = (s[i-1] == p[j-1] or p[j-1] == '?') and dp[i-1][j-1] 
                
    return dp[len(s)][len(p)]

def isMatch2(s, p):
    """
    :type s: str
    :type p: str
    :rtype: bool
    """
    i,j=0,0
    start = -1
    m=0
    
    while i<len(s):
        if j<len(p) and (s[i]==p[j] or p[j]=='?'):
            i+=1
            j+=1
        elif j<len(p) and p[j]=='*':
            start = j
            j+=1
            m = i
        elif start!=-1:
            j = start+1
            m +=1
            i = m
        else:
            return False
    while j<len(p):
        if p[j]=='*': 
            j+=1
        else: 
            break    
    return j==len(p)

45.jump-game-ii 跳跃游戏 II

解题思路:题目说明一定可以跳到队末 要次数最少
找到调到队尾的最靠前的一个点 将队尾移到这个点 跳动次数+1 pos记录当前的地址
反复寻找
begin用来记录重新开始寻找的点
如果开头是1则直接进行跳跃 次数+1 begin+1 及略过开头若干个1

def jump(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    begin = 0
    pos = 0 
    num = 0
    l = len(nums)
    if l<2:
        return num
    
    while True:
        while nums[pos]==1:
            pos+=1
            if pos==l-1:
                break
            num+=1
            begin = pos
        while pos+nums[pos]<l-1:
            pos+=1
        num +=1
        if pos==begin or pos==l-1:
            break
        l = pos+1
        pos = begin
    return num

135.candy 分发糖果

解题思路:初始化每人一个糖
从1开始遍历队列 与前一个位置比较如果 分数比前一个位置大 那么糖的数量为前一个位置+1
倒序队列和糖果list 再一次从1开始遍历队列 相当于倒的在比较一次
此时如果分数比前一个位置大 那么糖的数量为max(当前数量,前一个位置+1)
最后求糖果list的和

def candy(ratings):
    """
    :type ratings: List[int]
    :rtype: int
    """
    l = len(ratings)
    if l==0:
        return 0
    candys =[1]*l
    
    for i in range(1,l):
        if ratings[i]>ratings[i-1]:
            candys[i] = candys[i-1]+1
            
    candys.reverse()
    ratings.reverse()
    for i in range(1,l):
        if ratings[i]>ratings[i-1]:
            candys[i] = max(candys[i],candys[i-1]+1)
    return sum(candys)

321.create-maximum-number 拼接最大数

解题思路:findNum()在一个数组中取n个数的子序列 顺序不变 但是序列最大 参考402.remove-k-digits
mergeNum() 将两个list在不改变其内部顺序的条件下 合并成一个list 并使得list最大
将问题分解为若干个小问题
问题 从nums1,nums2中取k个数 组合成一个最大list 并且从n1,n2中取得数顺序不变:
分解为:
1.从nums1中取i个数,得到最大序列tmp1
2.从nums2中取k-i个数,得到最大序列tmp2
3.合并tmp1,tmp2得到最大序列tmp
ps:
注意i,k-i与nums的大小
在merge两个list时遇到一样的 要继续比较后面的值

def maxNumber(nums1, nums2, k):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :type k: int
    :rtype: List[int]
    """
    def findNum(num,n):
        l = len(num)
        if l==0:
            return []
        k = l-n
        stack = []
        move = k
        stack.append(num[0])
        for i in num[1:]:
            while i>stack[-1] and move>0:
                stack.pop()
                move -=1
                if len(stack)==0:
                    break
            stack.append(i)
        while move>0:
            stack.pop()
            move-=1
        return stack
    
    def mergeNum(l1,l2):
        ret = []
        tmp1 = l1[:]
        tmp2 = l2[:]
        tmp1.append(-1)
        tmp2.append(-1)
        i,j=0,0
        while (i<len(l1) or j<len(l2)): 
            if tmp1[i]>tmp2[j]:
                ret.append(tmp1[i])
                i+=1
            elif tmp1[i]<tmp2[j]:
                ret.append(tmp2[j])
                j+=1
            else:
                tmpi = min(i+1,len(l1))
                tmpj = min(j+1,len(l2))
                while tmp1[tmpi]==tmp2[tmpj]:
                    tmpi = min(tmpi+1,len(l1))
                    tmpj = min(tmpj+1,len(l2))
                    if tmpi==len(l1) and tmpj==len(l2):
                        break
                if tmp1[tmpi]>tmp2[tmpj]:
                    ret.append(tmp1[i])
                    i+=1
                else:
                    ret.append(tmp2[j])
                    j+=1
        return ret

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值