leetcode1 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
思路
返回下标,一般来说是不要排序了。
可以近似暴力搜索,但是是
O
(
n
2
)
O(n^2)
O(n2),写的不好会超时。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
lens = len(nums)
j=-1
for i in range(1,lens):
temp = nums[:i]
if (target - nums[i]) in temp:
j = temp.index(target - nums[i])
break
if j>=0:
return [j,i]
可以把数据做键,索引做键值存入hash表,在hash表中查找存不存在能配对的另一个元素
复杂度降为
O
(
n
)
O(n)
O(n)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dic = {}
for index,num in enumerate(nums):
dic[num] = index
for index,num in enumerate(nums):
index2 = dic.get(target-num)
if index2 and index2!=index:
return [index,index2]
leetcode167: 升序数组的两数之和
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:
输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
left,right = 0,len(numbers)-1
while left<right:
if numbers[left]+numbers[right] == target:
return [left+1,right+1]
elif numbers[left]+numbers[right] < target:
left+=1
else:
right-=1
return []
leetcode15 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
固定第一个数,剩余两个数用两个指针查找。
注意去重。
- 固定的第一个数去重(遍历时相同则跳过)
- 双指针指向的数去重(局部遍历时相同则跳过)
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res,k=[],0
for k in range(len(nums)-2):
if nums[k]>0:break
if k>0 and nums[k] == nums[k-1]:continue # 跳过相同的nums[k]
i,j = k+1,len(nums)-1
while i<j:
s = nums[i]+nums[j]
if s<-nums[k]:
i+=1
while i<j and nums[i]==nums[i-1]:
i+=1 #跳过相同的nums[i]
elif s>-nums[k]:
j-=1
while i<j and nums[j] == nums[j+1]:
j-=1
else:
res.append([nums[k],nums[i],nums[j]])
i+=1
j-=1
while i<j and nums[i] ==nums[i-1]:i+=1
while i<j and nums[j] == nums[j+1]:j-=1
return res
leetcode18 四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
思路
如果直接类比三数和,那就是固定两个数,另外两个数用双指针查找,复杂度时
O
(
n
3
)
O(n^3)
O(n3)
为了避免重复,可以先用set保存结果(自动去重,set添加元素的方法是set.add()
)
然后再把set中的元素放入list
for item in set_xx: list_xx.append(list(item)
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
res = set()
for i in range(len(nums)-3):
for j in range(i+1,len(nums)-2):
left,right = j+1,len(nums)-1
new_tar = target-nums[i]-nums[j]
while left<right:
su = nums[left]+nums[right]
if su<new_tar:
left+=1
elif su>new_tar:
right -=1
else:
res.add((nums[i],nums[j],nums[left],nums[right]))
left+=1
right-=1
rec = []
for i in res:
rec.append(list(i))
return rec
leetcode16 最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
#print(nums)
n = len(nums)
res = float("inf")
for i in range(n-2):
if i > 0 and nums[i] == nums[i-1]:
continue
left = i + 1
right = n - 1
while left < right :
#print(left,right)
cur = nums[i] + nums[left] + nums[right]
if abs(res-target) > abs(cur-target):
res = cur
if cur == target:
return target
elif cur > target:
right -= 1
else:
left += 1
return res
leetcode259 较小的三数和
oh。。没权限。。之后再补