剑指Offer刷题记录 - part two(python版本)

11. 两数之和 II - 输入有序数组

题目要求

给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

解题思路

采用双指针的方式最简单,时间复杂度为O(n)。

代码

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        i, j = 0, len(numbers) - 1
        while i < j:
            sum_num = numbers[i] + numbers[j]
            if sum_num == target:
                return [i+1, j+1]
            elif sum_num < target:
                i += 1
            elif sum_num > target:
                j -= 1

在这里插入图片描述

12.两数之和 III - 数据结构设计

题目要求

设计一个接收整数流的数据结构,该数据结构支持检查是否存在两数之和等于特定值。

实现 TwoSum 类:

TwoSum() 使用空数组初始化 TwoSum 对象
void add(int number) 向数据结构添加一个数 number
boolean find(int value) 寻找数据结构中是否存在一对整数,使得两数之和与给定的值相等。如果存在,返回 true ;否则,返回 false 。

加上一个示例可能会更好理解。
在这里插入图片描述

解题思路

这道题比较特殊,笔者是第一次遇到。先借鉴一下大佬们的解法。
在这里插入图片描述
注意:这里的self类似于js的this,一定要有这个,不然程序不知道你指代的是什么。

上述思路比较巧妙的一点是,用输入的值作为字典的key,而出现的次数作为字典的value。这两种情况也是很巧的,若两个数相加为value时(所要找的值,而非字典的value),要么它们的次数是至少为1,要么一定大于1。

比如,value=4,若2出现了两次,它们的Key相等,但它们在字典中的次数一定是有一个大于1的。若是【1,3】,它们出现的次数可以一样,也可以不一样,但是至少是出现一次的,不可能是0。

代码

class TwoSum:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.numbers = {}

    def add(self, number: int) -> None:
        """
        Add the number to an internal data structure..
        """
        if number not in self.numbers:
            self.numbers[number] = 1
        else:
            self.numbers[number] += 1

    def find(self, value: int) -> bool:
        """
        Find if there exists any pair of numbers which sum is equal to the value.
        """
        for key in self.numbers:
            key2 = value - key
            if key2 in self.numbers:
                if self.numbers[key2] >= 1 and key != key2:
                    return True
                elif self.numbers[key2] > 1 and key == key2:
                    return True
        return False



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

在这里插入图片描述

13.两数之和 IV - 输入 BST

题目要求

解题思路

解法一:中序遍历法,先把给定的数存入一个列表中,然后使用双指针来判断两者的和是否等于k值。(后面的部分类似于上面的解法)

解法二:非中序遍历法。这是从其他大佬那里借鉴来的方法,即直接按节点及其左右子节点搜索的方法。由于题目给定了一棵二叉树,就不像之前的题目可能会出现同样的数字,所以本题就可以使用集合set()。 本解法是直接对所有节点进行搜索,即若所有节点值都在字典中,就返回True,若没有则继续搜索当前节点的左右子节点,直到找到所有符合的值。

解法二的方法速度果然快很多,因为不用多次对比,而直接顺着树进行搜索。

代码

# 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: TreeNode, k: int) -> bool:
        # 解法一:中序遍历法
        nums = []
        def mid_order(root):
            if root:# 要判断root是否存在,不存在则直接返回false
                mid_order(root.left)
                nums.append(root.val)
                mid_order(root.right)
        mid_order(root)
        i, j = 0, len(nums) - 1
        while i < j:
            if nums[i] + nums[j] == k:
                return True
            elif nums[i] + nums[j] > k:
                j -= 1
            else:
                i += 1
        return False
        
        # 解法二:直接按节点及左右子节点搜索法
        self.comp = set() #用set保存已经出现过数的互补数,若一旦出现互补数,则本体已经出现过!!
        def find(root):
            if not root:
                return False
            if root.val in self.comp:
                return True
            else:
                self.comp.add(k - root.val)
            return find(root.left) or find(root.right)
        return find(root)

解法一:
在这里插入图片描述
解法二:
在这里插入图片描述

14.三数之和

题目要求

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

解题思路

借鉴一下大佬们的解题思路。
在这里插入图片描述
在这里插入图片描述

代码

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        
        n=len(nums)
        res=[]
        if(not nums or n<3):
            return []
        nums.sort()
        res=[]
        for i in range(n):
            if(nums[i]>0):
                return res
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L=i+1
            R=n-1
            while(L<R):
                if(nums[i]+nums[L]+nums[R]==0):
                    res.append([nums[i],nums[L],nums[R]])
                    while(L<R and nums[L]==nums[L+1]):
                        L=L+1
                    while(L<R and nums[R]==nums[R-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1
                else:
                    L=L+1
        return res 

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值