我为两个和问题提供了三种解决方案
给出所有整数数组,返回两个数字的指数,以便它们加起来成为一个特定的目标。
您可以假设每个输入将具有恰好一种解决方案,并且您可能不会两次使用 same 元素。
示例:
Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
一种是操纵数据结构
class Solution1(): #Manipulate Data
def twoSum(self, nums: List[int], target: int) -> List[List[int]]:
nums_d = {}
couples = []
#O(n)
for i in range(len(nums)):
nums_d.setdefault(nums[i], []).append(i)
for i in range(len(nums)):
complement = target - nums[i]
nums_d[nums[i]].pop(0) #remove the fixer
result = nums_d.get(complement)#hash table to search
#if j is not Nne and j is not empty.
if result: #if exits, it should be [j]
couples.append([nums[i], complement])
return couples
第二是多个条件检查
class Solution2: #Double Pass Approach
def twoSum(self, nums, target) -> List[List[int]]:
"""
:type nums: List[int]
:type target: int
"""
if len(nums) < 2:
return []
couples = []
nums_d:dict = {}
for i in range(len(nums)):
#nums_d.setdefault(nums[i], []).append(i)
nums_d[nums[i]] = i
for i in range(len(nums)):
complement = target - nums[i]
# nums_d[nums[i]].pop(0) #remove the fixer
if nums_d.get(complement) != None and nums_d.get(complement) != i:
couples.append([nums[i], complement])
return couples
第三只操作索引
class Solution: 3#Single Pass Approach
def twoSum(self, nums, target) -> List[List[int]]:
"""
:type nums: List[int]
:type target: int
"""
nums_d:dict = {}
couples = []
if len(nums) < 2:
return []
for i in range(len(nums)):
complement = target - nums[i]
logging.debug(f"complement: {complement}")
logging.debug(f"Check: {nums_d.get(complement)}")
if nums_d.get(complement) != None:
# couples.append([i, nums_d.get(complement)])
couples.append([nums[i], complement])
nums_d[nums[i]] = i
logging.debug(f"nums_d: {nums_d}")
return couples
和我的测试用例
class TestCase(unittest.TestCase):
# logging.debug("Class TestCase started.")
"""
Test for 'twoSum.py'
"""
def setUp(self):
self.solution = Solution1()
self.solution2 = Solution2()
self.solution3 = Solution3()
def test_two_sum3(self):
#random is present
target = 30
nums = random.sample(range(20), k=20)
print(f"\ntarget: {target} \nnums: {nums}")
#Input no-replacement nums
print('Solution Length:', len(self.solution.twoSum(nums, target)))
print('result:', self.solution.twoSum(nums, target))
print('Solution2 Length:', len(self.solution2.twoSum(nums, target)))
print('result2:', self.solution2.twoSum(nums, target))
print('Solution3 Length:', len(self.solution3.twoSum(nums, target)))
print('result3:', self.solution3.twoSum(nums, target))
unittest.main()
获取结果
nums: [8, 0, 2, 15, 18, 5, 4, 14, 3, 12, 17, 19, 11, 10, 6, 16, 7, 13, 1, 9]
Solution Length: 4
result: [[18, 12], [14, 16], [17, 13], [19, 11]]
Solution2 Length: 8
result2: [[18, 12], [14, 16], [12, 18], [17, 13], [19, 11], [11, 19], [16, 14], [13, 17]]
Solution3 Length: 4
result3: [[12, 18], [11, 19], [16, 14], [13, 17]]
.
----------------------------------------------------------------------
Ran 3 tests in 0.001s
我是solution2的粉丝。
如何重写if nums_d.get(complement) != None and nums_d.get(complement) != i:
避免重复?
答案 0 :(得分:2)
首先,我想说的是,您的解决方案与两个问题总和不完全匹配。
您可以假设每个输入都只有一个解决方案,并且您可能不会两次使用相同的元素。
实际上,您不需要记录多个结果,只需查找并返回即可。
根据您的解决方案和测试用例,在此我假设您的方案适用于结果不正确且忽略重复对的数据。
我想出了两种方法来改善您的Solution2
,也优化了您的代码,您可以进行比较并从中学习:
set
和sorted pair
删除重复项:class Solution4:
def twoSum(self, nums, target) -> List[List[int]]:
if len(nums) < 2:
return []
couples = set()
nums_d = {v: i for i, v in enumerate(nums)} # init by dict comprehension
for i, v in enumerate(nums): # enumerate is better here
complement = target - v
if nums_d.get(complement, i) != i: # use sentinel, more concise
# if complement in nums_d and nums_d[complement] != i: # more understandable
couples.add(tuple(sorted((nums[i], complement)))) # need immutable in set
return list(map(list, couples)) # convert back to list
complement >= v
(排序对)对,比上面更有效的对。 注意:此解决方案不会通过输入中的[15,15]这样的情况,我只是假设没有这样的边缘情况,因为您的3个原始解决方案都不会通过。 / strike>
class Solution5:
def twoSum(self, nums, target) -> List[List[int]]:
if len(nums) < 2:
return []
couples = []
nums_d = {v: i for i, v in enumerate(nums)} # init by dict comprehension
for i, v in enumerate(nums): # enumerate is better here
complement = target - v
if complement >= v:
if nums_d.get(complement, i) != i: # use sentinel, more concise
# if complement in nums_d and nums_d[complement] != i: # more understandable
couples.append([v, complement])
return couples
顺便说一句,我是Solution3
的粉丝,它在遍历时更新索引,这是一种常见的技术,使用更少的额外空间和一次遍历。
希望对您有所帮助,如果还有其他问题,请发表评论。 :)