日常系列LeetCode《13·综合应用1篇》

Posted 常某某的好奇心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常系列LeetCode《13·综合应用1篇》相关的知识,希望对你有一定的参考价值。

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)

综合 <直接模拟、经典查找>

lc 1【top100】:两数之和
https://leetcode.cn/problems/two-sum/
提示:
2 <= nums.length <= 10^4
-10^9 <= nums[i] <= 10^9
-10^9 <= target <= 10^9
只会存在一个有效答案
进阶:
你可以想出一个时间复杂度小于 O(n^2) 的算法吗?

#方案一:线性查找
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
    	#o(1),o(n^2)
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i]+nums[j]==target:
                    return [i,j]
        return -1
        
#方案二:排序二分查找->hash查找
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        #o(n),o(2n)
        #预处理 
        hashmap=
        hashmap = x: i for i, x in enumerate(nums)
        #
        for i in range(len(nums)):
            x=nums[i]
            if target-x in hashmap:
                j=hashmap[target-x]
                if j!= i:
                   return [i,j]
        return -1 
        
#方案三:hash查找优化
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        #o(n)
        hashmap=
        #o(n)
        for i in range(len(nums)):
            x=nums[i]
            if target-x in hashmap:
                j=hashmap[target-x]
                #if j!= i: 不需要
                return [i,j]
            hashmap[nums[i]]=i
        return -1 

lc 167【剑指 006】:两数之和:输入有序数组
https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/
提示:
2 <= numbers.length <= 3 * 10^4
-1000 <= numbers[i] <= 1000
numbers 按 非递减顺序 排列
-1000 <= target <= 1000
仅存在一个有效答案

#方案一:二分查找法
class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        n=len(numbers)
        for i in range(n):
            x=numbers[i]
            #O(logn),O(1)
            index=self.bi_search(numbers,i+1,n-1,target-x)
            if index!=-1:return [i+1,index+1]#题目首位为1
        return []
    
    def bi_search(self,numbers,left,right,t):
        while left<=right:
            mid=left+(right-left)//2
            if numbers[mid]==t:return mid
            elif numbers[mid]>t:right=mid-1
            else:left=mid+1
        return -1

#方案二:双指针法
class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        left,right=0,len(numbers)-1
        #o(n),o(1)
        while left<right:
            s=numbers[left]+numbers[right]
            if target==s:return [left+1,right+1]
            elif target>s:left=left+1
            else:right=right-1
        return []

lc 170:两数之和:数据结构设计
https://leetcode.cn/problems/two-sum-iii-data-structure-design/

#方案一:二分查找
class TwoSum:

    def __init__(self):
        self.numbers=[]
        self.is_sorted=False

    def add(self, number: int) -> None:
        self.numbers.append(number)
        self.is_sorted=False

    def find(self, value: int) -> bool:
        #o(nlogn),o(n)
        if not self.is_sorted:
            self.numbers.sort()
            self.is_sorted=True
        #
        left,right=0,len(self.numbers)-1
        while left < right:
            s = self.numbers[left] + self.numbers[right]
            if s ==value:return True
            elif s<value:left += 1
            else:right -= 1
        return False

# Your TwoSum object will be instantiated and called as such:
# obj = TwoSum()
# obj.add(number)
# param_2 = obj.find(value)

#方案二:hash查找
class TwoSum:
    def __init__(self):
        self.numbers=dict()
  
    def add(self, number: int) -> None:
        if number in self.numbers:self.numbers[number]+=1
        else:self.numbers[number]=1
    
    def find(self, value: int) -> bool:
        #o(n),o(n)
        for num in self.numbers.keys():
            t=value-num
            if t==num and self.numbers[t]>=2:return True
            elif t!=num and t in self.numbers:return True
        return False

# Your TwoSum object will be instantiated and called as such:
# obj = TwoSum()
# obj.add(number)
# param_2 = obj.find(value)

lc 653:两数之和:输入 BST
https://leetcode.cn/problems/two-sum-iv-input-is-a-bst/
提示:
二叉树的节点个数的范围是 [1, 10^4].
-10^4 <= Node.val <= 10^4
题目数据保证,输入的 root 是一棵 有效 的二叉搜索树
-10^5 <= k <= 10^5

#方案一:二分查找
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def findTarget(self, root: Optional[TreeNode], k: int) -> bool:
        #o(n)
        nums=[]  
        #中序遍历:o(n)
        def inorder(node):
            if not node:return 
            inorder(node.left)
            nums.append(node.val)
            inorder(node.right)
        inorder(root)
        #
        left,right=0,len(nums)-1
        while left<right:
            s=nums[left]+nums[right]
            if s==k:return True
            elif s>k:right-=1
            else:left+=1
        return False

#方案二:一次遍历hash查找
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def findTarget(self, root: Optional[TreeNode], k: int) -> bool:
        #o(n),o(n)
        s=set()
        #DFS
        def find(node):
            if not node:return False
            if k-node.val in s:return True
            s.add(node.val)
            return find(node.left) or find(node.right) #key
        return find(root) #return

lc 15【剑指 007】【top100】:三数之和
https://leetcode.cn/problems/3sum/
提示:
3 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5


#方案一:二分查找(去重技巧)
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        #
        nums.sort()
        res=[]
        #o(n^2)
        for i in range(len(nums)-2):
            #去重1
            if i>=1 and nums[i]==nums[i-1]:continue
            #
            t=-nums[i]
            left,right=i+1,len(nums)-1
            while left<right:
                s=nums[left]+nums[right]
                if s==t:
                    res.append([nums[i],nums[left],nums[right]])
                    #去重2
                    #写法1
                    # while left < right:
                    #     left = left + 1
                    #     if nums[left - 1] != nums[left]: break
                    # while left < right:
                    #     right = right - 1
                    #     if nums[right + 1] != nums[right]: break
                    #写法2
                    while left<right and nums[left]==nums[left+1]:left+=1
                    left+=1
                    while left<right and nums[right]==nums[right-1]:right-=1
                    right-1
                #
                elif s>t:right-=1
                else:left+=1
        return res

lc 18 :四数之和
https://leetcode.cn/problems/4sum/
提示:
1 <= nums.length <= 200
-10^9 <= nums[i] <= 10^9
-10^9 <= target <= 10^9

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        #
        nums.sort()
        res = []
        #o(n^3)
        for i in range(len(nums) - 3):
            #去重1
            if i>=1 and nums[i]==nums[i-1]:continue
            for j in range(i+1,len(nums)-2):
                #去重2
                if j>=i+2 and nums[j]==nums[j-1]:continue
                #
                s1=nums[i]+nums[j]
                left,right=j+1,len(nums)-1
                while left<right:
                    s=s1+nums[left]+nums[right]
                    if s==target:
                        res.append([nums[i],nums[j],nums[left],nums[right]])
                        #去重3
                        while left<right and nums[left]==nums[left+1]:left+=1
                        left+=1
                        while left<right and nums[right]==nums[right-1]:right-=1
                        right-=1
                    elif s>target:
                        right-=1
                    else:left+=1
        return res      

lc 349 : 两个数组的交集
https://leetcode.cn/problems/intersection-of-two-arrays/
提示:【去重】
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000

#方案一:线性查找
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        #o(m*n),o(min(m,n))
        res=set()
        for n1 in nums1:
            for n2 in nums2:
                if n1==n2:
                    res.add(n1)
        return list(res) #key 
#方案二:二分查找
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        #o(nlogn+mlogn),o(min(m,n))
        res=set()
        nums2.sort() #nlogn
        for n1 in nums1:
            #o(logn)
            if self.contain(nums2,n1):
                res.add(n1)
        return list(res) #key

    def contain(self,nums,t):
        left,right=0,len(nums)-1
        while left<=right:
            mid=left+(right-left)//2 
            if nums[mid]==t:return True
            elif nums[mid]>t:right=mid-1
            else:left=mid+1
        return False

#方案三:hash查找
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        #o(n+m),o(min(m,n)+n)
        res=set()#o(min(m,n))
        set2=set(nums2) #o(n),o(n)
        #o(m)
        for n1 in nums1:
            #o(1)
            if n1 in set2:
                res.add(n1)
        #
        return list(res)

#方案四:双指针排序去重
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        #o(nlogn+mlogm),o(min(m,n))
        res=[]
        nums1.sort()
        nums2.sort()
        #
        i=j=0
        while i<len(nums1) and j<len(nums2):
            if nums1[i]==nums2[j]:
                if len(res)==0 or nums1[i]!=res[-1]:
                    res.append(nums1[i])
                #注:位置
                i+=1
                j+=1
            elif nums1[i]>nums2[j]:
                j+=1
            else:i+=1
        return res

lc 350 :两个数组的交集 II
https://leetcode.cn/problems/intersection-of-two-arrays-ii/
提示:【不去重】
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
进阶:
如果给定的数组已经排好序呢?你将如何优化你的算法?
如果 nums1 的大小比 nums2 小,哪种方法更优?
如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

#方案一:哈希查找
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        #o(min(m,n)+n),o(m+n)
        res=[]
        map1=num:0 for num in nums1
        for num in nums1:map1[num]+=1
        #
        for n in nums2:
            if n in map1 and map1.get(n)>0:
                res.append(n)
                map1[n]-=1
        #
        return res
#方案二:二分查找
cl

以上是关于日常系列LeetCode《13·综合应用1篇》的主要内容,如果未能解决你的问题,请参考以下文章

日常系列LeetCode《5·数学篇》

日常系列LeetCode《9·哈希查找篇》

日常系列LeetCode《6·位运算篇》

日常系列LeetCode《1·数组常用技巧篇》

日常系列LeetCode《8·二分查找篇》

日常系列LeetCode《10·栈和队列篇》