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