leecode

满足和/积的子数组

leecode713,乘积小于k的子数组。滑动窗口,双指针。考虑清楚边界条件。

class Solution:
    def numSubarrayProductLessThanK(self, nums, k) -> int:
        s = e = 0
        tmp = nums[0]
        ans = 0
        while s < len(nums) and e < len(nums):
            if tmp <k:
                ans += e-s+1
                if e<len(nums)-1:
                    e += 1
                    tmp *= nums[e]
                else:
                    break
            else:
                while s<e and s<len(nums)-1 and tmp >= k:
                    tmp /= nums[s]
                    s += 1
                if tmp>=k and s == e and e < len(nums)-1:
                    e += 1
                    tmp *= nums[e]
                if e == len(nums) -1 and s == e and tmp >= k:
                    break
        return ans


if __name__ == "__main__":
    solution = Solution()
    nums = [1,2,3]
    k = 0
    ans = solution.numSubarrayProductLessThanK(nums,k)
    print(ans)

leecode560,和为k的子数组,前缀和(连续和)+哈希表(空间换时间),注意前缀和以及哈希表的构建更新顺序。

import collections
class Solution:
    def subarraySum(self, nums, k: int) -> int:
        prefix = [0]*len(nums)
        tmp = 0
        hash_table = collections.defaultdict(int)
        hash_table[0] = 1


        ans = 0
        for i in range(len(nums)):
            tmp  += nums[i] 
            prefix[i] = tmp
            ans += hash_table[prefix[i]-k]
            hash_table[tmp] += 1
        return ans


if __name__ == "__main__":
    solution = Solution()
    nums = [1]
    k = 0
    ans = solution.subarraySum(nums,k)
    print(ans)

leecode1,两数字之和,哈希表(空间换时间),注意哈希表的更新顺序。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hash_table = {}
        for i in range(len(nums)):
            if target - nums[i] in hash_table:
                return [i,hash_table[target - nums[i]]]
            hash_table[nums[i]] = i

leecode15,三数字之和,排序+双指针

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        nums.sort()
        ans = []
        for first in range(n):
            if first > 0 and nums[first] == nums[first-1]:
                continue
            third = n - 1
            target = -nums[first]
            for second in range(first+1,n):
                if second > first + 1 and nums[second] == nums[second - 1]:
                    continue
                while second < third and nums[second] + nums[third] > target:
                    third -= 1
                if second == third:
                    break
                if nums[second] + nums[third] == target:
                    ans.append([nums[first],nums[second],nums[third]])
        return ans

leecode653,两树之和(输入二叉搜素树),中序遍历+双指针

class Solution:
    def findTarget(self, root: Optional[TreeNode], k: int) -> bool:
        self.ans = []
        def morder(root):
            if root == None:
                return 
            morder(root.left)
            self.ans.append(root.val)
            morder(root.right)
            return
        morder(root)
        s = 0
        e = len(self.ans)-1
        while s < e:
            if self.ans[s] + self.ans[e] == k:
                return True
            elif self.ans[s] + self.ans[e] > k:
                e -= 1
            else:
                s += 1
        return False

leecode167,两数之和(输入有序数组),双指针

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        self.ans = numbers
        k = target
        s = 0
        e = len(self.ans)-1
        while s < e:
            if self.ans[s] + self.ans[e] == k:
                return [s+1,e+1]
            elif self.ans[s] + self.ans[e] > k:
                e -= 1
            else:
                s += 1

leecode724,寻找数组的中心下表(左右元素和相等),优化前缀和+后缀和

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        suffix = [0]*(len(nums)+1)
        tmp = 0
        for i in range(len(nums)-1,-1,-1):
            tmp += nums[i]
            suffix[i] = tmp
        prefix = 0
        for i in range(len(nums)):
            if prefix == suffix[i+1]:
                return i
            prefix += nums[i]


        return -1

最()子序列

leecode1143,最长公共子序列,动态规划,可以优化空间,但是要特别注意优化空间后转移方程的书写,用dp[]存储上一行的状态,用dp_1存储当前状态极限优化空间可以根据len(text1)和len(text2)的大小来交换text1和text2;可以用递归来写,但是要注意记忆化搜索,注意自顶向下递归。

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        dp = [[0]*(len(text2) + 1) for _ in range(len(text1) + 1)]
        for i in range(1,len(text1)+1):
            for j in range(1,len(text2)+1):
                if text1[i-1] == text2[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                else:
                    dp[i][j] = max(dp[i][j-1],dp[i-1][j])
        return dp[len(text1)][len(text2)]



## 优化空间版本
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        dp = [0]*(len(text2)+1)
        dp_1 = 0
        for i in range(1,len(text1)+1):
            dp_1 = 0
            for j in range(1,len(text2)+1):
                if text1[i-1] == text2[j-1]:
                    dp[j-1],dp_1 = dp_1,dp[j-1] + 1
                    
                                        
                else:
                    dp[j-1],dp_1 = dp_1,max(dp_1,dp[j])
            dp[len(text2)] = dp_1
            
        return dp_1
## 递归版本
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        @lru_cache(None)
        def dfs(i,j):
            if i == 0 or j== 0:
                return 0
            if text1[i-1] == text2[j-1]:
                return dfs(i-1,j-1) +1
            else:
                return max(dfs(i-1,j),dfs(i,j-1))

        return dfs(len(text1),len(text2))

leecode128,最长连续序列,哈希表+判断优化,判断num-1是否出现过,对于连续的序列,只计算最开头的那一次

class Solution:
    def longestConsecutive(self, nums) -> int:
        ans = 0
        hash_table = set(nums)
        for num in nums:
            if num - 1 not in hash_table:
                tmp = num + 1
                tmp_ans = 1
                while tmp in hash_table:
                    tmp_ans += 1
                    tmp += 1
                ans = max(ans,tmp_ans)
        return ans

offer93,最长斐波那契数列,动态规划+哈希表+判断优化,注意这里没有重复元素,所以第三元素的判断可以用哈希表,否则有重复元素的存在的时候就不能用哈希表存。

class Solution:
    def lenLongestFibSubseq(self, arr: List[int]) -> int:
        indices = {x:i for i,x in enumerate(arr)}
        ans = 0
        dp = [[0] * len(arr) for _ in range(len(arr))]
        for i,x in enumerate(arr):
            for j in range(i-1,-1,-1):
                if arr[j]*2 <= arr[i]:
                    break
                if x - arr[j] in indices:
                    k = indices[x-arr[j]]
                    dp[j][i] = max(3,dp[k][j] + 1)
                    ans = max(dp[j][i],ans)
        return ans

offer1027,最长等差数列,动态规划,和offer93类似,但是不能用哈希表来存第三个元素,因为数组有重复元素,本题遍历第一个元素和公差,dp[i][j]代表以nums[i]结尾的公差为j的等差数列的长度,因为公差可能为负数,因此要特殊处理,同时加上某个值使其变非负。

class Solution:
    def longestArithSeqLength(self, nums) -> int:
        n = len(nums)
        ans = 0
        div = max(nums) - min(nums)
        dp = [[1]*(div*2+1) for _ in range(n)]
        for i in range(1,n):
            for k in range(i):
                j = nums[i] - nums[k] + div
                dp[i][j] = max(dp[i][j],dp[k][j] + 1)
                ans = max(ans,dp[i][j])
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值