1月6号 491,492,494

遇到一些难的还是做不太出来

只能继续刷了, 进度 -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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值