之前在github, 简书上写更新,现在搬到CSDN上。话不多说,直接上题目
16 3Sum Closest
Given an array nums
of n integers and an integer target
, find three integers in nums
such that the sum is closest to target
. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example
Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
思路
和14题3Sum类似,由找到所有和为0的3个值,变为找到所有和离target
最近的3个值。首先将数组按升序nums
排序,再从左到右遍历。取一个值a
作为基准值,再从数组中在a
右边的值里选出两个值b
, c
,使得|target-a-b-c|
最小。
解法
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
def twoSumClosest(nums, c=0):
'''
从数组nums中找到组合(a, b),使得 |a + b - c|最小.
返回值:满足条件的a, b之和: a*+b*
'''
i = 0
j = len(nums)-1
result = nums[i]+nums[j]
while i < j:
s = nums[i]+nums[j]
if s == c:
return s
if abs(c-s)<abs(c-result):
result = s
if s > c:
j -= 1
elif s < c:
i += 1
return result
if len(nums) < 3:
return None
nums = sorted(nums) # 首先将nums排序
for i in range(len(nums)-2):
if i >= 1 and nums[i] == nums[i-1]: #跳过重复的a
continue
bc = twoSumClosest(nums[i+1:], target-nums[i]) #bc为满足条件的b,c之和
if target == nums[i]+bc: #如果a+b+c和target相等,直接返回target
return target
if i == 0: #i = 0时,赋result初值
result = nums[i]+bc
else:#当前的a+b+c比前一个a+b+c更加接近target时,更新result
if abs(target-nums[i]-bc)<abs(target - result):
result = nums[i] + bc
return result
14. 3Sum (Medium)
原题链接
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路
a+b+c=0
等价于a+b=-c
, 因此原问题转化为找到两个数a
和b
,使得a+b=-c
,这样就从3Sum的问题转化到2Sum
解法
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
def twoSum(nums, c=0):
'''
从数组nums中找到所有的组合(a, b),使得 a + b = c.
返回值:所有的和为-c的组合[[a1, b1, -c],[a2, b2, -c],..., [an, bn, -c]]
'''
result = []
i = 0
j = len(nums)-1
while i < j:
s = nums[i]+nums[j]
if s == c:
if [nums[i], nums[j], -c] not in result: #结果不能包含重复值
result.append([nums[i], nums[j], -c])
i += 1
j -= 1
elif s >c:
j -= 1
else:
i += 1
return result
result = []
if len(nums) < 3:
return result
nums = sorted(nums) # 首先将nums排序
for i in range(len(nums)):
if nums[i]>0: #nums[i]即为c. 由于数组从小到大排序,当c>0时三者之和不可能为0
break
if i >= 1 and nums[i] == nums[i-1]:#跳过重复的c
continue
r = twoSum(nums[i+1:], -nums[i])
result += r
return result
771 Jewels and Stones (original link)
You’re given strings J representing the types of stones that are jewels, and S representing the stones you have. Each character in S is a type of stone you have. You want to know how many of the stones you have are also jewels.
The letters in J are guaranteed distinct, and all characters in J and S are letters. Letters are case sensitive, so “a” is considered a different type of stone from “A”.
Example 1:
Input: J = “aA”, S = “aAAbbbb”
Output: 3
Example 2:
Input: J = “z”, S = “ZZ”
Output: 0
Solution 1: Brute force:reference
def numJewelsInStones(self, J, S):
result = 0
for j in J:
for s in S:
if j == s:
result += 1
return result
A more pythonic way:
def numJewelsInStones(self, J, S):
return sum(s in J for s in S)
Time complexity: O(|J|*|S|)
Space complexity: O(1)
Solution 2: Use set
def numJewelsInStones(self, J, S):
f = set(J)
return sum([s in f for s in S])
Time complexity: O(|J|*|S|)
The operation a in b
has different time complexity in list and set, see here:https://wiki.python.org/moin/TimeComplexity
a in b
in list: O(n)
a in b
in set: O(1)
807. Max Increase to Keep City Skyline (original link)
In a 2 dimensional array grid, each value grid[i][j] represents the height of a building located there. We are allowed to increase the height of any number of buildings, by any amount (the amounts can be different for different buildings). Height 0 is considered to be a building as well.
At the end, the “skyline” when viewed from all four directions of the grid, i.e. top, bottom, left, and right, must be the same as the skyline of the original grid. A city’s skyline is the outer contour of the rectangles formed by all the buildings when viewed from a distance. See the following example.
What is the maximum total sum that the height of the buildings can be increased?
Example:
Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]
Output: 35
Explanation:
The grid is:
[ [3, 0, 8, 4],
[2, 4, 5, 7],
[9, 2, 6, 3],
[0, 3, 1, 0] ]
The skyline viewed from top or bottom is: [9, 4, 8, 7]
The skyline viewed from left or right is: [8, 7, 9, 3]
The grid after increasing the height of buildings without affecting skylines is:
gridNew = [ [8, 4, 8, 7],
[7, 4, 7, 7],
[9, 4, 8, 7],
[3, 3, 3, 3] ]
Analysis
The skyline is the maximum value in each row/column of grid
.
The element (i,j) in newGrid
should be min{row[j], col[i]}
, where row
and col
are the skylines of grid
.
So the result is the sum of difference between each element in grid
and newGrid
.
In the first traverse, compute row
and col
.
In the second traverse, set the value of newGrid
based on row
and col
.
Finally calculate the difference.
Solution: reference
class Solution:
def maxIncreaseKeepingSkyline(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
rows, cols = list(map(max, grid)), list(map(max, zip(*grid)))
return sum(min(i, j) for i in rows for j in cols) - sum(map(sum, grid))
Time complexity: O(n*n)
804. Unique Morse Code Words (original link)
International Morse Code defines a standard encoding where each letter is mapped to a series of dots and dashes, as follows: “a” maps to “.-”, “b” maps to “-…”, “c” maps to “-.-.”, and so on.
For convenience, the full table for the 26 letters of the English alphabet