268. Missing Number - easy
题目描述
给定一个包含n个不同数字的数组,数字来自0, 1, 2, …, n,找到缺失的数字。
例子
Example 1:
Input: [3,0,1]
Output: 2
Example 2:
Input: [9,6,4,2,3,5,7,0,1]
Output: 8
思想
要求时间复杂度-O(n),空间复杂度O(1)
利用数学:0…n的和为n(n+1)/2,然后减去sum(nums)
解法
class Solution(object):
def missingNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
return n*(n+1)//2 - sum(nums)
62. Unique Paths
题目描述
在m*n方格的左上角有一个机器人,机器人每次只能向下或向右移动。问机器人到达右下角有多少中不同走法?
例子
Example 1:
Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1.Right -> Right -> Down
2.Right -> Down -> Right
3.Down -> Right -> Right
Example 2:
Input: m = 7, n = 3
Output: 28
思想
(法1 - DP)
dp[i][j] = dp[i-1][j] + dp[i][j-1]
当然可以优化空间
(法2 - 数学解法)
从(1,1)到达(m,n),则机器人一共走了m+n-2步。在这些步数中,一共向下走m-1步,向右走n-1步,所以结果为组合数为
C
m
+
n
−
2
m
−
1
=
(
m
+
n
−
2
)
!
(
m
−
1
)
!
(
n
−
1
)
!
C_{m + n - 2}^{m - 1} = {{\left( {m + n - 2} \right)!} \over {\left( {m - 1} \right)!\left( {n - 1} \right)!}}
Cm+n−2m−1=(m−1)!(n−1)!(m+n−2)!
解法1
DP,复杂度:时间-O(mn),空间-O(mn)
class Solution(object):
def uniquePaths(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
dp = [[0] * n for _ in range(m)]
for i in range(m):
for j in range(n):
if i == 0 or j == 0:
dp[i][j] = 1
else:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[-1][-1]
(空间优化)时间-O(mn),空间-O(n)
class Solution(object):
def uniquePaths(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
dp = [0] * n
for i in range(m):
for j in range(n):
if i == 0 or j == 0:
dp[j] = 1
else:
dp[j] += dp[j-1]
return dp[-1]
解法2
组合数。
class Solution(object):
def uniquePaths(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
p1 = p2 = 1
for i in range(m, m+n-1): # p2: 1..n
p1 *= i
p2 *= (i-m+1)
return p1/p2
462. Minimum Moves to Equal Array Elements II
题目描述
给定一个非空的整数数组,求解使得数组所有元素相等的最小移动次数。移动 - 所选元素加1或减1
例子
Input: [1,2,3]
Output: 2
Explanation:
Only two moves are needed (remember each move increments or decrements one element):
[1,2,3] => [2,2,3] => [2,2,2]
思想
假设数组长度为n,最终的目标值为target = nums[i]。则有i个数比target小,有n-i个数大于等于target。
(法1 - 计算)
将nums排序,则前i个数的移动次数为target - num;后n-i个数的移动次数为num - target,所以总移动次数为
∑
i
=
0
n
−
1
∣
n
u
m
s
[
i
]
−
t
a
r
g
e
t
∣
=
  
i
×
t
a
r
g
e
t
−
n
u
m
s
[
:
i
]
+
n
u
m
s
[
i
:
]
−
(
n
−
i
)
×
t
a
r
g
e
t
=
  
n
u
m
s
[
i
:
]
−
n
u
m
s
[
:
i
]
+
i
×
t
a
r
g
e
t
−
(
n
−
i
)
×
t
a
r
g
e
t
=
  
s
u
m
(
n
u
m
s
)
+
(
2
i
−
n
)
×
t
a
r
g
e
t
−
2
×
n
u
m
s
[
:
i
]
\begin{aligned} \sum\limits_{i = 0}^{n - 1} {\left| {nums[i] - {\rm{target}}} \right|} = &\; i \times {\rm{target}} - nums[:i]{\rm{ + }}nums[i:] - (n - i) \times {\rm{target }} \\ = &\; nums[i:] - nums[:i]{\rm{ + i}} \times {\rm{target}} - (n - i) \times {\rm{target }} \\ = &\; {\rm{sum(}}nums{\rm{)}}+({\rm{2}}i - n) \times {\rm{target}} - {\rm{2}} \times nums[:i] \end{aligned}
i=0∑n−1∣nums[i]−target∣===i×target−nums[:i]+nums[i:]−(n−i)×targetnums[i:]−nums[:i]+i×target−(n−i)×targetsum(nums)+(2i−n)×target−2×nums[:i]
所以只需 min ( ( 2 i − n ) × t a r g e t − 2 × n u m s [ : i ] ) , t a r g e t = n u m s [ i ] \min (({\rm{2}}i - n) \times {\rm{target}} - {\rm{2}} \times nums[:i]), \quad target{\rm{ = }}nums[i] min((2i−n)×target−2×nums[:i]),target=nums[i]
(法2 - 优化) - 取中位数即可
排序后,target为数组中的某个数;则所需求解目标为
min
(
∑
i
=
0
n
−
1
∣
n
u
m
s
[
i
]
−
t
a
r
g
e
t
∣
)
\min \left( {\sum\limits_{i = 0}^{n - 1} {\left| {nums[i] - {\rm{target}}} \right|} } \right)
min(i=0∑n−1∣nums[i]−target∣)
当target取值为中位数时,上式取得最小值。
证明如下:
若数组长度2m+1为奇数,则中位数左右两边各有m个数。设左边所有数与中位数的差值和为x, 右边所有数与中位数的差值和为y。
1)选择中位数:则所有需要移动的次数为x+y。
2)不选择中位数,例如选择median-1。则左边的数移动到median-1需要(x-n)次,而中位数右边的数移动到median-1需要(y+n)次,同时中位数还需移动一次。这样总的移动次数 = (x-n) + (y+n) + 1 = x+y+1
若数组长度为偶数,这种情况下中位数为两个,选择任意一个均可以。可以先让左中位数左边的数都移动到左中位数的位置右中位数…,然后两者拼接。
解法1
复杂度:时间-O(nlogn)排序;空间-O(1)
class Solution(object):
def minMoves2(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums.sort()
summ = sum(nums)
prev = 0
n = len(nums)
cnt = float('inf')
for i in range(n):
cnt = min(cnt, summ + (2*i-n)*nums[i] - 2*prev)
prev += nums[i]
return cnt
解法2
target取中位数即可。
class Solution(object):
def minMoves2(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums.sort()
median = nums[len(nums)//2]
cnt = 0
for num in nums:
cnt += abs(num - median)
return cnt