数学专题3 - leetcode343. Integer Break/650. 2 Keys Keyboard/223. Rectangle Area

343. Integer Break

题目描述

给定一个正整数n,把它拆分成至少两个正整数的和,并最大化这些整数的乘积。返回所能得到的最大乘积。

例子
Example 1:

Input: 2
Output: 1

Explanation: 2 = 1 + 1, 1 × 1 = 1.

Example 2:

Input: 10
Output: 36

Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.

思想
(法1 - DP)
dp[i] = max(dp[i], max(i, dp[j]) * max(i-j, dp[i-j]))
比如5 = 2+3,积为6;而integerBreak(2)=1,integerBreak(3)=2

(法2 - 找规律)
2:1+1,
3:1+2,4:2+2,5:3+2,
6:3+3,7:3+4,8:3+3+2,
9:3+3+3,10:3+3+4,11:3+3+3+2,
12:3+3+3+3,13:3+3+3+4,14:3+3+3+3+2
可以看出(不考虑n = 2或3):
当n = 6/9/12时,直接拆分成3+3+…3的形式;
当n = 4/7/10/13时,可以直接拆分成3+…+3+4的形式;
当n = 5/8/11/14时,可以直接拆分成3+3+…+3+2的形式;

解法1
DP

class Solution(object):
    def integerBreak(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n == 2:
            return 1
        if n == 3:
            return 2
        dp = [i for i in range(n+1)]
        for i in range(4, n+1):
            for j in range(1, i):
                dp[i] = max(dp[i], dp[j] * dp[i-j])
        return dp[-1]

解法2
找规律

class Solution(object):
    def integerBreak(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n == 2 or n == 3:
            return n-1
        
        if n % 3 == 0:
            return 3 ** (n//3)
        if n % 3 == 1:
            return 4 * 3 ** (n//3 - 1)
        return 2 * 3 ** (n//3)

650. 2 Keys Keyboard

题目描述

最初记事本上只有一个字符’A’存在。 每一步你可以在此记事本上执行两个操作之一:
1)全部复制:复制记事本上的所有字符(不允许部分复制);
2)粘贴:粘贴上次复制的字符。

给定一个数字n, 输出获得n个’A’的最小操作步数。(1≤n≤1000)

例子

Input: 3
Output: 3

Explanation:
Intitally, we have one character ‘A’.
In step 1, we use Copy All operation.
In step 2, we use Paste operation to get ‘AA’.
In step 3, we use Paste operation to get ‘AAA’.

思想
(暴力 - DP)
dp[i]表示得到i个 ‘A’ 所需的最小操作步数。
则dp[i] = min(dp[i], dp[j] + i//j),j=1,2…i-1

(递归)

(数学)
假设a1,a2…,am是n的质因子。则最后一步肯定粘贴了 n/a1个’A’ - a1次,倒数第二步肯定粘贴了n/a1/a2个’A’ - a2次… 总次数为质因子的和。(对于每个质数x,最少次数是x次操作)

解法1
暴力 - DP,复杂度:时间 - O(n^2),空间 - O(n)

class Solution(object):
    def minSteps(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [i for i in range(n+1)]
        dp[1] = 0
        for i in range(2, n+1):
            for j in range(2, i):
                if i % j == 0:
                    dp[i] = min(dp[i], dp[j] + i//j)
        return dp[-1]

解法2
递归

class Solution(object):
    def minSteps(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n == 1:
            return 0
        res = n
        for i in range(2, n):
            if n % i == 0:
                res = min(res, self.minSteps(i) + n/i)
        return res

解法3
质因子的和

class Solution(object):
    def minSteps(self, n):
        """
        :type n: int
        :rtype: int
        """
        res = 0
        factor = 2
        while n > 1:
            while n % factor == 0:
                n /= factor
                res += factor
            factor += 1
        return res

223. Rectangle Area

题目描述

求被2D平面中的直线矩形覆盖的总面积。每个矩形由其左下角和右上角坐标定义。

例子
在这里插入图片描述

Input: A = -3, B = 0, C = 3, D = 4, E = 0, F = -1, G = 9, H = 2
Output: 45

思想
重点是求出两矩形交集的面积,交集肯定也是矩形,所以重点是求出交集矩形的长和宽。
长 - 一维坐标轴线段AC与线段EG的交集长度 → min(C, G) - max(A, E);
宽 - 一维坐标轴线段BD与线段FH的交集长度 → min(D, H) - max(B, F)。
若长/宽小于0,则没有重叠。

解法

class Solution(object):
    def computeArea(self, A, B, C, D, E, F, G, H):
        """
        :type A: int
        :type B: int
        :type C: int
        :type D: int
        :type E: int
        :type F: int
        :type G: int
        :type H: int
        :rtype: int
        """
        length = min(C, G) - max(A, E)
        width = min(D, H) - max(B, F)
        area = (C - A) * (D - B) + (G - E) * (H - F)
        if length <= 0 or width <= 0:
            return area
        return area - length * width
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值