题目 面试题 17.16. 按摩师
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
示例
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。
示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。
示例 3:
输入: [2,1,4,5,3,1,1,3]
输出: 12
解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。
解题思路
- 根据条件可知 只能找不相邻的两个数
- 假设
opt[i]
表示到下标为 i 的最佳方案 - 选择下标为 i 的方案 opt[i-2] + arr[i]
- 不选择下标为 i 的方案 opt[i]
- 再比较 这两个的大小
- 找出口
- 当数组
arr
只有一个数字的时候 最大数opt[0] = arr[0]
- 当数组arr
有两个数字的时候 最大数opt[1] = max(arr[0],arr[1])
- 根据思路可推到出公式
代码 一维数组
- 递归的 时间复杂度 是 $O(n)$
python
class Solution: def massage(self, nums: List[int]) -> int: lenNums = len(nums) if nums == None or lenNums ==0: return 0 opt = [0] * lenNums if lenNums == 1: return nums[0] if lenNums == 2: return max(nums[0],nums[1]) opt[0] = nums[0] opt[1] = max(nums[0],nums[1]) for i in range(2,lenNums): a = opt[i-2] + nums[i] b = opt[i-1] opt[i] = max(a,b) return opt[lenNums-1]
java
public class Solution { public int massage(int[] nums) { int len = nums.length; if (len == 0) { return 0; } if (len == 1) { return nums[0]; } int[] opt = new int[len]; opt[0] = nums[0]; opt[1] = Math.max(nums[0],nums[1]); for(int i = 2;i<len;i++) { int a = opt[i-2] + nums[i]; int b = opt[i-1]; opt[i] = Math.max(a,b); } return opt[len-1]; } }
方法二 递归
- 递归的 时间复杂度 是 $O(n^2)$
- (该方法会超时,只是多提供一个思路)
class Solution:
def massage(self, nums: List[int]) -> int:
lenNums = len(nums)
if nums == None or lenNums ==0:
return 0
return self.opt(nums,lenNums-1)
def opt(self,nums,lenNums):
if lenNums == 0 :
return nums[0]
elif lenNums == 1 :
return max(nums[0],nums[1])
else:
a = self.opt(nums,lenNums-2) + nums[lenNums] # 选择nums[i]
b = self.opt(nums,lenNums-1) # 不选nums[i]
return max(a,b)
PREVIOUS面试题29. 顺时针打印矩阵
NEXT面试题 08.11. 硬币