Two Sum

Two sum

两数之和

https://leetcode.cn/problems/two-sum/
class Solution:
    """
    @param numbers: An array of Integer
    @param target: target = numbers[index1] + numbers[index2]
    @return: [index1, index2] (index1 < index2)
    """
    def twoSum1(self, numbers, target):
        # 方法1: hash 
        from collections import defaultdict
        my_dict = defaultdict(int)
        res = [-1, -1]

        for i,n in enumerate(numbers):
            if target - n in my_dict.keys():
                if i < my_dict[target - n]:
                    res.append(i)
                    res.append(my_dict[target - n])
                else:
                    res.append(my_dict[target - n])
                    res.append(i)
            else:
                my_dict[n] = i
        
        return res
 
    def twoSum(self, numbers, target):
        # 方法2:数组排序+双指针
        nums = [ (n, i) for i,n in enumerate(numbers)]
        nums.sort()

        left, right = 0, len(nums) - 1
        while left < right:
            if nums[left][0] + nums[right][0] == target:
                return sorted( [nums[left][1], nums[right][1]] )
            elif nums[left][0] + nums[right][0] > target:
                right -= 1
            else:
                left += 1
        
        return [-1, -1]

 

 

 

Two Sum III - Data structure design

class TwoSum:
 def __init__(self):
 self.nums = []

    """
    @param number: An integer
    @return: nothing
    """
    def add(self, number):
        # write your code here
        self.nums.append(number)
        idx = len(self.nums) - 1
 
        # 1.始终将 number 放在数组的最后一个位置,然后将number与前面的元素进行比较,调整位置
        # 2.时间复杂度:add O(N), find O(N)
        while idx > 0 and self.nums[idx - 1] > self.nums[idx]:
            self.nums[idx-1], self.nums[idx] = self.nums[idx], self.nums[idx-1]
            idx -= 1
 
    """
    @param value: An integer
    @return: Find if there exists any pair of numbers which sum is equal to the value.
    """
    def find(self, value):
        # write your code here
        left, right = 0, len(self.nums) - 1
        while left < right:
            s = self.nums[left] + self.nums[right]
            if s < value:
                left += 1
            elif s > value:
                right -= 1
            else:
                return True
        return False

 





class TwoSum:
    # 时间复杂度:add O(1), find O(N^2)
    def __init__(self):
        self.nums2cnt = {}
    """
    @param number: An integer
    @return: nothing
    """
    def add(self, number):
        # write your code here
        self.nums2cnt[number] = self.nums2cnt[number] + 1 if number in self.nums2cnt else 1
            
    """
    @param value: An integer
    @return: Find if there exists any pair of numbers which sum is equal to the value.
    """
    def find(self, value):
        # write your code here
        for num1 in self.nums2cnt:
            num2 = value - num1
            num2_cnt = 2 if num1 == num2 else 1
            if num2 in self.nums2cnt and self.nums2cnt[num2] >= num2_cnt:
                return True
        return False

 

Two Sum IV - Input is a BST

方法1:extra space

 

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param: : the root of tree
    @param: : the target sum
    @return: two numbers from tree which sum is n
    """
    def in_order(self, root, n, node_set):
        if not root: return 
        self.in_order(root.left, n, node_set)
        if root.val in node_set:
            self.res = [n - root.val, root.val]
        else:
            node_set.add(n - root.val)
        self.in_order(root.right, n, node_set)

    def twoSum(self, root, n):
        # write your code here
        if not root: return 
        self.res = None
        node_set = set()
        self.in_order(root, n, node_set)
        return self.res

 

 

方法2:在中序序列上进行双指针

 

"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    # 基于 predecessor 与 successor + 双指针 Time O(h * n) Space O(1) 
    # 448. Inorder Successor in BST 
    # 915. Inorder Predecessor in BST
    """
    @param: : the root of tree
    @param: : the target sum
    @return: two numbers from tree which sum is n
    """

    def twoSum(self, root, n):
        # write your code here
        if not root: return
        # 在中序序列上进行二分
        min_node = self.get_min_node(root)
        max_node = self.get_max_node(root)
        left_node, right_node = min_node, max_node

        while left_node != right_node:
            pivot = left_node.val + right_node.val
            if pivot == n:
                return [left_node.val, right_node.val]
            elif pivot < n:
                left_node = self.get_successor_node(root, left_node)
            else:
                right_node = self.get_predecessor_node(root, right_node)
            
        return 
    
    def get_min_node(self, root):
        node = root
        while node.left:
            node = node.left
        return node
    
    def get_max_node(self, root):
        node = root
        while node.right:
            node = node.right
        return node

    def get_successor_node(self, root, p):
        # 找中序序列中第一个比p大的元素
        node, upper = root, None
        while node:
            # 当前node大于p,那么当前node向左走
            if node.val > p.val:
                upper = node
                node = node.left 
            # 当前node小于p,那么当前node向右走
            else:
                node = node.right
        return upper 

    def get_predecessor_node(self, root, p):
        # 找中序序列中第一个比p小的元素
        node, lower = root, None
        while node:
            if node.val < p.val:
                lower = node
                node = node.right
            else:
                node = node.left
        return lower
        

 

 

1879 · Two Sum VII

sorted in ascending order of absolute value

方法1:use extra space

 

def two_sum_v_i_i(self, nums: List[int], target: int) -> List[List[int]]:
        # write your code here
        self.dic = {}
        res = []

        for idx, num in enumerate(nums):
            if target - num in self.dic:
                if idx < self.dic[target - num]:
                    res.append([idx, self.dic[target - num]])
                else:
                    res.append([self.dic[target-num], idx])
            else:
                self.dic[num] = idx
        
        return res

 

 

方法2:xxx在数组的max和min中进行二分

 

from typing import (
    List,
)

class Solution:
    """
    @param nums: the input array
    @param target: the target number
    @return: return the target pair
    """
    def two_sum_v_i_i(self, nums: List[int], target: int) -> List[List[int]]:
        # write your code here
        n = len(nums)
        if not nums: return 

        left, right = 0, 0
        for i in range(n):
            if nums[i] > nums[right]: right = i
            if nums[i] < nums[left]: left = i

        res = []
        while left >= 0 and right < n and nums[left] < nums[right]:
            if nums[left] + nums[right] < target:
                left = self.nextleft(nums, left)
            elif nums[left] + nums[right] > target:
                right = self.nextright(nums, right)
            else:
                if left < right: res.append([left, right])
                else: res.append([right, left])

                left = self.nextleft(nums, left)
        return res
        
    def nextleft(self, nums, left):
        n = len(nums)
        # 如果要查找 负数left的 后一个元素(left+1)
        if nums[left] < 0:
            # 如果left左边有负数,那么left的下一个元素就是其左边的第一个负数
            for i in range(left - 1, -1, -1):
                if nums[i] < 0:
                    return i
            # 如果left左边没有负数,那么left的下一个元素就是从0到n的第一个正数
            for i in range(n):
                if nums[i] >= 0:
                    return i
            return -1

        # 如果left是正数, 那么left的下一个元素就是其右边的第一个正数
        for i in range(left + 1, n):
            if nums[i] >= 0:
                return i 
        return -1
    

    def nextright(self, nums, right):
        n = len(nums)
        # 如果要查找 正数right的 前一个元素(right-1)
        if nums[right] > 0:
            # [0,-1,2,-3,4] 中的 4
            # 如果right左边有正数,那么right的前一个元素就是从右向左第一个大于0的数
            for i in range(right-1, -1, -1):
                if nums[i] > 0: 
                    return i
            # 如果right左边全是非正数,那么right的前一个元素就是从0到n的第一个非正
            # [0,-1,2,-3,4] 中的 2
            for i in range(n):
                if nums[i] <= 0:
                    return i
            return -1

        # 如果要查找 非正数right 的前一个元素。从right到右的第一个负数
        # [0,-1,2,-3,4] 中的-1
        for i in range(right+1, n):
            if nums[i] <= 0:
                return i

        return -1

 

 

443 · Two Sum - Greater than target

class Solution:
    """
    @param nums: an array of integer
    @param target: An integer
    @return: an integer
    """
    def twoSum2(self, nums, target):
        nums.sort()
        res = 0

        left, right = 0, len(nums) - 1
        while left < right:
            if nums[left] + nums[right] <= target:
                left += 1
            elif nums[left] + nums[right] > target:
                res += (right - left)
                right -= 1

        return res
View Code

 

 

 3sum closest

 59 · 最接近的三数之和

class Solution:
    """
    @param numbers: Give an array numbers of n integer
    @param target: An integer
    @return: return the sum of the three integers, the sum closest target.
    """
    def threeSumClosest(self, numbers, target):
        # 方法:k数之和的题目
        # 首先对数组排序
        # k-2重for循环遍历前k-2个元素,使用双指针确定最后的2个元素     
        # 定义一个:全局的最接近和res,
        # 比较:当前的三个元素与target的差的绝对值 和 res与target的差的绝对值,进而更新全局最接近和res

        numbers.sort()
        res = None

        for i in range(len(numbers) - 2):
            left, right = i + 1, len(numbers) - 1
            while left <right:
                cur_sum = numbers[i] + numbers[left] + numbers[right]
                if res is None or abs(cur_sum - target) < abs(res - target):
                    res = cur_sum

                if cur_sum <= target:
                    left += 1
                else:
                    right -= 1
        
        return res
View Code

 

 

 

 
posted @ 2022-04-10 20:16  7aughing  阅读(27)  评论(0编辑  收藏  举报