leetcode:1713.得到子序列的最少操作次数

 solution1:

        最开始的想法,递归,for循环target,如果arr里面没有则加1,如果有递归,两种情况。1、插入新的target为[1,3],新的arr为匹配到的位置后面的部分[9,4,1,2,3,4],这里还有一个细节,就是有可能arr有相同的数。2、不插入,加1,新的target[1,3],arr保持不变。然后对两种结果取最小值

count =0
clist =[]
def compc(target,arr,count):
    for i in range(len(target)):
        num = target[i]
        loc = np.where(arr==num)
        if(len(loc[0]) ==0):
            count = count+1
        else:
            if(i==len(target)-1):
                return count
            clistt = []
            countb = compc(target[i + 1:], arr, count + 1)
            clistt.append(countb)
            for j in range(len(loc[0])):
                a = int(loc[0][j])
                arrt = arr[a:]
                counta = compc(target[i+1:], arrt,count)
                clistt.append(counta)
            count= min(clistt)
            clist.append(count)
            return count
    return count
c = compc(target,arr,count)
print(clist)
if len(clist)>1:
    c = min(clist)
print(c)

很显然,空间复杂度和时间复杂度严重超标。

 solution2:

        看了一眼解析,哦,找最长公共子序列,那就动态规划,就去看了一眼动态规划的逻辑,直接暴力复现

        这块的关键是转换了思想,在arr里寻找包含的target里的元素以及对应的位置,我感觉我下次还是想不到。。。。

#转换为最长递增子序列,暴力动态规划
pos =[]
tmp =0
for i in range(len(arr)):
    if arr[i] in target:
        al = np.where(target==arr[i])
        pos.append(al[0])
dp = np.ones(len(pos))
for i in range(len(pos)):
    val = pos[i]
    for j in range(i):
        if(pos[j]<val):
            dp[i]=max(dp[i],dp[j]+1)
c =len(target) -int(max(dp))
print(c)

很显然还是超时。

 solution3:

        这时,target的特点就要突出了,递增序列,意味着寻找递增的子序列,那么第二层for循环就可以简化了,这个逻辑,pos里面的元素可以通过对比大小来进行删除,将for循环换成了while(这里用了二分法来插入)

#二分法 动态规划
pos =[]
for i in range(len(arr)):
    if arr[i] in target:
        al = np.where(target==arr[i])
        pos.append(al[0])
dp = []
dp.append(pos[0])
tmp =1
for i in range(1,len(pos)):
    if(dp[len(dp)-1]<pos[i]):
        dp.append(pos[i])
    else:
        l=0
        r = len(dp)-1
        loc =r
        while(l<=r):
            mid = (l+r)//2
            if(dp[mid]>=pos[i]):
                loc = mid
                r = mid-1
            else:
                l = mid+1
        dp[loc] =pos[i]
c =len(target) -len(dp)
print(c)

 发现还是超时,,emmm,又看了一眼解析,发现一个for循环和第二个for循环完全可以合并啊,用了bisect.bisect_left二分查找的库,我寻思库能比我写的快点?然后又又又试了一下

 solution4:

#两个for循环可以合并
pos = []
dp = []
for i in range(len(arr)):
    if arr[i] in target:
        al = np.where(target == arr[i])
        # pos.append(al[0])
        idx = al[0]
        if (len(dp) == 0 or idx > dp[len(dp) - 1]):
            dp.append(idx)
        else:
            site = bisect.bisect_left(dp, idx)
            if site < len(dp):
                dp[site] = idx
            else:
                dp.append(idx)
c = len(target) - len(dp)

        还是不行,还是超时,然后我把答案里面的c++版本拷进去提交了一下,是真的快,应该是python本身的局限性吧。看起来逻辑是一样的,行吧,思想最重要,就到这吧。

学了忘,忘了学,学了还得忘,忘了学,学了忘,忘了还得学。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值