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
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