遇到一些难的还是做不太出来
只能继续刷了, 进度 -42
491. Increasing Subsequences
给定一个序列,你的任务就是寻找所有的上升子列,每个子列的长度至少为2
Example:
Input: [4, 6, 7, 7]
Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
可以看到如果是相同的数也可以视作是上升序列。
那思路就是DFS遍历就行了,然后做一些去重处理即可。
代码如下:
class Solution(object):
def findSubsequences(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = set()
self.dfs(nums, 0, [], res)
return list(map(list, res))
def dfs(self, nums, index, path, res):
if tuple(path) in res:
return
if len(path)>=2:
res.add(tuple(path))
used = set()
for i in range(index, len(nums)):
if nums[i] in used:
continue
used.add(nums[i])
if (path and nums[i]>=path[-1]) or not path:
self.dfs(nums, i+1, path+[nums[i]], res)
492. Construct the Rectangle
简答题,题目描述看题目描述
代码:
class Solution(object):
def constructRectangle(self, area):
"""
:type area: int
:rtype: List[int]
"""
w = int(area**0.5)
while w>0:
if area%w==0:
break
w-=1
return [int(area/w), w]
494. Target Sum
给定数字 a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an,以及target, 每一个 a i a_i ai前面可以自由加上 + + +或者 − - −,最后将这些数求和,求问有多少种添加 + . − +.- +.−的方式使得最后的和等于target。
Example 1:
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
There are 5 ways to assign symbols to make the sum of nums be target 3.
如果是暴力遍历的话,那么这道题是
O
(
2
n
)
O(2^n)
O(2n)的复杂度,那么思路很明显,我们该如何用dp
的方式去减少计算复杂度。
一个思路就是把所有可能的和求出来,最后看有多少是等于S的
代码如下:
class Solution(object):
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
dp = {nums[0]:1, -nums[0]:1} if nums[0] != 0 else {0:2}
for num in nums[1:]:
tdp = {}
for key, values in dp.items():
tdp[key+num] = tdp.get(key+num, 0) + values
tdp[key-num] = tdp.get(key-num, 0) + values
dp = tdp
return dp.get(S, 0)
其中之所以需要tdp是因为我们只需要保存上一步的结果就可以了。
其中这题还有另外一种思路。
假如正的部分数字的和是p
,负的部分数字的和是n
。
那么有p+n=sum(nums), p-n=s
,所以有p = (sum(nums)+s)/2
所以,这题就转化成了一个求target的问题,在nums
挑选数字,最后等于p
的组合数是多少。
那这就是一道典型的动态规划题目。
令dp[i][j]
为数据集为nums[:i+1]
,target为j的时候的组合数,
那么dp[i+1][j] = dp[i][j-nums[i+1]] + dp[i][j]
,要么不选num[i+1]
进来,要么选num[i+1]
进来
代码如下:
class Solution(object):
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
if sum(nums)<S or -sum(nums)>S:
return 0
target, val = divmod(sum(nums)+S, 2)
if val!=0:
return 0
dp = [[1]+[0]*(target) for _ in range(len(nums)+1)]
for i in range(1, len(nums)+1):
for j in range(0, target+1):
if j >= nums[i-1]:
dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]
else:
dp[i][j] = dp[i-1][j]
return dp[-1][-1]
其实每次运算都只涉及到dp[i]
以及dp[i-1]
,所以我们可以改写成滚动数组的形式减少空间复杂度。
代码如下:
class Solution(object):
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
if sum(nums)<S or -sum(nums)>S:
return 0
target, val = divmod(sum(nums)+S, 2)
if val!=0:
return 0
dp = [1] + [0]*target
for c in nums:
for i in range(len(dp)-1, -1, -1):
if i>=c:
dp[i]+=dp[i-c]
return dp[-1]