Given four integer arrays nums1
, nums2
, nums3
, and nums4
all of length n
, return the number of tuples (i, j, k, l)
such that:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
Example 1:
Input: nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] Output: 2 Explanation: The two tuples are: 1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
思路:
比起昨天的2sum,就是多了一重循环,把每两组array的number之和的所有可能视为2sum里的一个array,再直接套用2sum的解法。
因为不用去重,所以更为简单。今天接下来的两道题都是需要去重的。
class Solution(object):
def fourSumCount(self, nums1, nums2, nums3, nums4):
"""
:type nums1: List[int]
:type nums2: List[int]
:type nums3: List[int]
:type nums4: List[int]
:rtype: int
"""
# It is easy since repetition is allowed.
sum12 = {}
count = 0
for i in nums1:
for j in nums2:
sum12[0-(i+j)] = sum12.get(0-(i+j),0) + 1
for i in nums3:
for j in nums4:
if j+i in sum12:
count += sum12[(i+j)]
return count
# computation complexity O(n^2)
算法复杂度 O(n^2)
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]]
such that i != j
, i != k
, and j != k
, and nums[i] + nums[j] + nums[k] == 0
.
Notice that the solution set must not contain duplicate triplets.
Example 1:
Input: nums = [-1,0,1,2,-1,-4] Output: [[-1,-1,2],[-1,0,1]] Explanation: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0. nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0. nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0. The distinct triplets are [-1,0,1] and [-1,-1,2]. Notice that the order of the output and the order of the triplets does not matter.
思路:元素需要被输出,不止是计数,考虑用双指针。先对数组进行排序。从左到右选定第一个元素,然后以这个元素右侧隔壁的元素为left,排序数组的最右为right指针。接下来根据sum的大小调整左右指针就好。
注意去重,允许相同的元素出现在一个3sum tuple中,但不要出现一样的tuple。所以是在遍历左右指针的时候,跳过重复的。
注意提前结束的几个标志:if nums[i] > 0: return result #排序后第一个元素必须大于0.
while right > left # right的值一定大于等于left的,因为在之后的if elif else中right和left有可能相等,所以这里是right>left,而不是>=。
solution:
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums = sorted(nums)
result = []
# i is the first(smallest) value of the 3 in the 3Sum
for i in range(len(nums)):
if nums[i] > 0:
return result
if i > 0 and nums[i] == nums[i-1]: # skip the same value to avoid repetation
continue
left = i+1
right = len(nums)-1
while right > left: # Once left right pointers change in the loop, this rule should be checked again to ensure the availability.
sum_ = nums[i] + nums[left] +nums[right]
if sum_ < 0:
left += 1
elif sum_ > 0:
right -= 1
else:
result.append([nums[i], nums[left], nums[right]])
# skip the repeated items
while right > left and nums[right] == nums[right-1]:
right -= 1
while right > left and nums[left] == nums[left+1]: # do not forget while right > left。
left += 1
right -= 1
left += 1
return result
字典法:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result = []
nums.sort()
# 找出a + b + c = 0
# a = nums[i], b = nums[j], c = -(a + b)
for i in range(len(nums)):
# 排序之后如果第一个元素已经大于零,那么不可能凑成三元组
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i - 1]: #三元组元素a去重
continue
d = {}
for j in range(i + 1, len(nums)):
if j > i + 2 and nums[j] == nums[j-1] == nums[j-2]: # 三元组元素b去重
continue
c = 0 - (nums[i] + nums[j])
if c in d:
result.append([nums[i], nums[j], c])
d.pop(c) # 三元组元素c去重
else:
d[nums[j]] = j
return result
算法复杂度均为O(n^2)
Given an array nums
of n
integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]]
such that:
0 <= a, b, c, d < n
a
, b
, c
, and d
are distinct.nums[a] + nums[b] + nums[c] + nums[d] == target
You may return the answer in any order.
Example 1:
Input: nums = [1,0,-1,0,-2,2], target = 0 Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
思路:比起上一题3sum,就是多加一重循环。遍历头两个元素组合的所有可能性,然后再用双指针找接下来两个元素。
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
# compare with 3sum,add a for-loop
nums.sort()
n = len(nums)
result = []
for i in range(n):
if nums[i] > target and nums[i] > 0 and target > 0: #early stop, not necessary
break
if i > 0 and nums[i] == nums[i-1]:
continue
for j in range(i+1, n):
if nums[i] + nums[j] > target and target > 0: #early stop, not necessary
break
if j > i+1 and nums[j] == nums[j-1]:
continue
left, right = j+1, n-1
while left < right:
s = nums[i] + nums[j] + nums[left] + nums[right]
if s == target:
result.append([nums[i], nums[j], nums[left], nums[right]])
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
elif s < target:
left += 1
else:
right -= 1
return result
Given two strings ransomNote
and magazine
, return true
if ransomNote
can be constructed by using the letters from magazine
and false
otherwise.
Each letter in magazine
can only be used once in ransomNote
.
Example 1:
Input: ransomNote = "a", magazine = "b" Output: false
思路:这题和昨天的题目类似。不过magazine里letter可能在赎金信里并没有用到。
class Solution(object):
def canConstruct(self, ransomNote, magazine):
"""
:type ransomNote: str
:type magazine: str
:rtype: bool
"""
counts = {}
for c in magazine:
counts[c] = counts.get(c, 0) + 1
for c in ransomNote:
if c not in counts or counts[c] == 0:
return False
counts[c] -= 1
return True
算法复杂度O(m+n)