我试图用二进制搜索解决方案解决leetcode中的threeSum问题,并对如何安排内部函数有疑问。
给出一个 n 个整数的数组
nums
,是否存在元素 a , b , cnums
中的 a + b + c = 0?在数组中找到所有零的三元组,它们的总和为零。注意:
解决方案集不得包含重复的三胞胎。
示例:
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
计划是将ThreeSum分解为twoSum和二分查找
1)首先对nums
进行排序,2)声明low_index= 0
和high_index = len(nums)
修复第一个数字,然后搜索其补语
3)因为num是排序的,所以如果number [1]> 0(目标)中断
4)如果数字重复,则跳过该数字并跳至下一个
5)two_sum
搜索number_1'补码,(目标-number_1)
class Solution:
def threeSum(self, nums, target=0) -> List[List[int]]:
"""
:type nums: List[int]
:type target: int
:rtype triplets: List[List[int]]
"""
if len(nums) < 3:
return []
nums.sort() #[1]
triplets = []
logging.debug(f"Level_1_nums: {nums}\n")
lo = 0
hi = len(nums) #[2]
while lo < hi -2:
if nums[lo] > target:break #[3]
while 0 < lo < hi -2 and nums[lo] == nums[lo-1]: #[4]
lo += 1
number_1 = nums[lo]
logging.debug(f"number_1: {nums[lo]}")
logging.debug(f"Level_2_nums: {nums[lo+1:hi]}\n")
two_sum(nums, target - number_1, lo+1, hi) #[5]
lo += 1 #increment
return triplets
6)two_sum
内的逻辑与上述相同,
7)binary_search number_2
的补码
8)如果找到,请将其附加到triplets
def two_sum(self, nums, target, lo, hi):
"""
:type nums: List[int]
:tppe target: int
:type triplets:
:rtype: List[List[int]]
"""
while lo < hi -1:
complement = target - nums[lo]
if self.bi_search(nums, complement, lo+1, hi) != None:
self.triplets.append([0-target, nums[lo], complement])
lo += 1
while lo < hi-1 and nums[lo] == nums[lo-1]:
lo += 1
9)基本的bi_search函数
def bi_search(self, a, x, lo=0, hi=None) -> int: #[9]
if hi == None:
hi = len(a)
if lo < 0:
raise ValueError('low must be non-negative')
while lo < hi:
mid = (lo + hi) // 2
if x == a[mid]: return x
if x > a[mid]: lo = mid + 1
if x < a[mid]: hi = mid
将它们放在一起:
from typing import List
import unittest
import loggiing
import random
logging.disable(level=logging.CRITICAL)
logging.basicConfig(level=logging.DEBUG, format="%(levelname)s %(message)s")
class Solution:
"""
Solve the problem by three module funtion
threeSum
two_sum
bi_search
"""
def threeSum(self, nums, target=0) -> List[List[int]]:
"""
:type nums: List[int]
:type target: int
:rtype triplets: List[List[int]]
inlude two_sum and bi_search function
"""
def two_sum(nums, target,lo, hi):
"""
:type nums: List[int]
:tppe target: int
:type triplets:
:rtype: List[List[int]]
"""
while lo < hi -1: # [6]
if nums[lo] > target: break # [6]
while 0 < lo < hi -1 and nums[lo] == nums[lo-1]: #[6]
lo += 1
number_2 = nums[lo] #[6]
logging.debug(f"number_2: {nums[lo]}")
logging.debug(f"Level_3_nums: {nums[lo+1:hi]} \n")
number_3 = bi_search(nums, target - number_2, lo+1, hi) #[7]
if number_3 != None: #[8]
triplets.append([number_1, number_2, number_3]) #[8]
logging.debug(f"triplets: {triplets}")
lo += 1
def bi_search(a, x, lo=0, hi=None): #[9]
"""
:type a: List[int]
:type x: int
:rtype: value not index
"""
if hi == None:
hi = len(a)
if lo < 0:
raise ValueError('low must be non-negative')
while lo < hi:
mid = (lo + hi) // 2
if x == a[mid]:
logging.debug(f"number_3: {x}")
return x
if x > a[mid]: lo = mid + 1
if x < a[mid]: hi = mid
#the whole implment block is at the bottom
if len(nums) < 3:
return []
nums.sort() #[1]
triplets = []
logging.debug(f"Level_1_nums: {nums}\n")
lo = 0
hi = len(nums) #[2]
while lo < hi -2:
if nums[lo] > target:break #[3]
while 0 < lo < hi -2 and nums[lo] == nums[lo-1]: #[4]
lo += 1
number_1 = nums[lo]
logging.debug(f"number_1: {nums[lo]}")
logging.debug(f"Level_2_nums: {nums[lo+1:hi]}\n")
two_sum(nums, target - number_1, lo+1, hi) #[5]
lo += 1 #increment
return triplets
和TestCase
class TestCase(unittest.TestCase):
"""
Tesing threeSum.py Solution class.
"""
def setUp(self):
self.solution = Solution()
def test_threeSum(self):
#nums = [0, 0, 0, 0, 0, 0]
nums = list(range(-100, 100))
target = 0
print(f"\n nums: {nums}\n target: {target}")
print(self.solution.threeSum(nums, target))
def test_threeSum_leetcode(self):
nums = [-1,1,2,-1,0, -8, -7, 0-4, -5, -3]
#nums = [1,2,-2,-1]
#nums = [-1,0,1,2,-1,-4]
# nums = list(range(-100, 100))
target = 0
print(f"\n nums: {nums}\n target: {target}")
print(f"res: {self.solution.threeSum(nums, target)}")
unittest.main()
我想精细地安排内部功能。因为所有工作代码都位于底部,因此很难阅读。
如何将主要逻辑放在C样式的顶部?
我尽力解决二进制搜索的问题,但仍然超出了时间限制。假定这种体面的解决方案使用leetcodes来使用哈希表。
如果坚持排序和二进制搜索,我又该如何改进代码呢?