Leetcode 198
解法一:递归+记录中间结果 = 记忆化搜索
class Solution:
def rob(self, nums: List[int]) -> int:
@cache
def dfs(i: int)->int:
if i < 0:
return 0
return max(dfs(i - 1), dfs(i - 2) + nums[i]);
return dfs(len(nums) - 1)
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
vector<int> memo(n, -1);
function<int(int)> dfs=[&](int i)->int {
if (i < 0) return 0;
if (memo[i] != -1) return memo[i];
int res = max(dfs(i - 1), dfs(i - 2) + nums[i]);
memo[i] = res;
return res;
};
return dfs(n - 1);
}
};
解法二:记忆化搜索翻译成递推
class Solution:
def rob(self, nums: List[int]) -> int:
f = [0] * (len(nums) + 2)
for i, x in enumerate(nums):
f[i + 2] = max(f[i + 1], f[i] + x)
return f[-1]
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
vector<int> f(n + 2);
for (int i = 0; i < n; i ++ )
f[i + 2] = max(f[i + 1], f[i] + nums[i]);
return f.back();
}
};
使用滚动数组进行空间优化
class Solution:
def rob(self, nums: List[int]) -> int:
f0 = f1 = 0
for i, x in enumerate(nums):
new_f = max(f1, f0 + x)
f0, f1 = f1, new_f
return f1
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
int f0 = 0, f1 = 0;
for (int x: nums) {
int new_f = max(f1, f0 + x);
f0 = f1, f1 = new_f;
}
return f1;
}
};
Leetcode 213
class Solution:
def rob1(self, nums: List[int])->int:
f0 = f1 = 0
for x in nums:
f0, f1 = f1, max(f1, f0 + x)
return f1
def rob(self, nums: List[int]) -> int:
return max(nums[0] + self.rob1(nums[2:-1]), self.rob1(nums[1:]))
class Solution {
private:
int rob1(vector<int> nums, int start, int end) {
int n = nums.size();
int f0 = 0, f1 = 0;
for (int i = start; i < end; i ++ ) {
int new_f = max(f1, f0 + nums[i]);
f0 = f1, f1 = new_f;
}
return f1;
}
public:
int rob(vector<int>& nums) {
int n = nums.size();
return max(nums[0] + rob1(nums, 2, n - 1), rob1(nums, 1, n));
}
};
Leetcode 494
01 背包变形,恰好的方案数
假设整个数组之和为 s s s,数组中添加正号的数之和为 p p p,那么数组中添加负号的数之和为 s − p s-p s−p,那么有 p − ( s − p ) = t a r g e t p - (s-p) =target p−(s−p)=target,继续有: p = ( t a r g e t + s ) / 2 p = (target + s) / 2 p=(target+s)/2现在问题就转换为了:从数组中找出若干个数,使得其和为 ( t a r g e t + s ) / 2 (target+s)/2 (target+s)/2 的方案数。
解法一:记忆化搜索
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
target += sum(nums)
if target < 0 or target % 2:
return 0
target //= 2
@cache
def dfs(i, c):
if i < 0:
return 1 if c == 0 else 0
if c < nums[i]: # 容量不够,只能不选
return dfs(i - 1, c)
return dfs(i - 1, c) + dfs(i - 1, c - nums[i])
return dfs(len(nums) - 1, target)
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
target += accumulate(nums.begin(), nums.end(), 0);
if (target < 0 || target % 2) return 0;
target /= 2;
// 两个参数的记忆化搜索
int n = nums.size(), cache[n][target + 1];
memset(cache, -1, sizeof cache);
function<int(int, int)> dfs = [&] (int i, int c)->int {
if (i < 0) return c == 0;
int &res = cache[i][c];
if (res != -1) return res;
if (c < nums[i]) return res = dfs(i - 1, c);
res = dfs(i - 1, c) + dfs(i - 1, c - nums[i]);
return res;
};
return dfs(n - 1, target);
}
};
解法二:递推
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
target += sum(nums)
if target < 0 or target % 2:
return 0
target //= 2
n = len(nums)
f = [[0] * (target + 1) for _ in range(n + 1)]
f[0][0] = 1
for i, x in enumerate(nums):
for c in range(target + 1):
if c < x:
f[i + 1][c] = f[i][c]
else:
f[i + 1][c] = f[i][c] + f[i][c - x]
return f[n][target]
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
target += accumulate(nums.begin(), nums.end(), 0);
if (target < 0 || target % 2) return 0;
target /= 2;
int n = nums.size(), f[n + 1][target + 1];
memset(f, 0, sizeof f);
f[0][0] = 1;
for (int i = 0; i < n; i ++ )
for (int c = 0; c <= target; c ++ )
if (c < nums[i]) f[i + 1][c] = f[i][c];
else f[i + 1][c] = f[i][c] + f[i][c - nums[i]];
return f[n][target];
}
};
解法三:使用滚动数组优化空间
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
target += sum(nums)
if target < 0 or target % 2:
return 0
target //= 2
n = len(nums)
f = [[0] * (target + 1) for _ in range(2)]
f[0][0] = 1
for i, x in enumerate(nums):
for c in range(target + 1):
if c < x:
f[(i + 1) % 2][c] = f[i % 2][c]
else:
f[(i + 1) % 2][c] = f[i % 2][c] + f[i % 2][c - x]
return f[n % 2][target]
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
target += accumulate(nums.begin(), nums.end(), 0);
if (target < 0 || target % 2) return 0;
target /= 2;
int n = nums.size(), f[2][target + 1];
memset(f, 0, sizeof(f));
f[0][0] = 1;
for (int i = 0; i < n; i ++ )
for (int c = 0; c <= target; c ++)
if (c < nums[i]) f[(i + 1) % 2][c] = f[i % 2][c];
else f[(i + 1) % 2][c] = f[i % 2][c] + f[i % 2][c - nums[i]];
return f[n % 2][target];
}
};
解法四:仅仅使用一个数组
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
target += sum(nums)
if target < 0 or target % 2:
return 0
target //= 2
f = [1] + [0] * target
for x in nums:
for c in range(target, x - 1, -1):
f[c] += f[c - x]
return f[target]
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
target += accumulate(nums.begin(), nums.end(), 0);
if (target < 0 || target % 2) return 0;
target /= 2;
int f[target + 1];
memset(f, 0, sizeof f);
f[0] = 1;
for (int x: nums)
for (int c = target; c >= x; c -- )
f[c] += f[c - x];
return f[target];
}
};
Leetcode 322
解法一:记忆化搜索
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
@cache
def dfs(i, c):
if i < 0:
return 0 if c == 0 else inf
if c < coins[i]:
return dfs(i - 1, c)
return min(dfs(i - 1, c), dfs(i, c - coins[i]) + 1)
ans = dfs(len(coins) - 1, amount)
return ans if ans < inf else -1
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int n = coins.size(), cache[n][amount + 1];
memset(cache, -1, sizeof(cache));
function<int(int, int)> dfs = [&](int i, int c)-> int {
if (i < 0) return c == 0 ? 0 : INT_MAX / 2;
int &res = cache[i][c];
if (res != -1) return res;
if (c < coins[i]) return res = dfs(i - 1, c);
res = min(dfs(i - 1, c), dfs(i, c - coins[i]) + 1);
return res;
};
int ans = dfs(n - 1, amount);
return ans < INT_MAX / 2 ? ans : -1;
}
};
解法二:翻译成递推
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
n = len(coins)
f = [[inf] * (amount + 1) for _ in range(n + 1)]
f[0][0] = 0
for i, x in enumerate(coins):
for c in range(amount + 1):
if c < x:
f[i + 1][c] = f[i][c]
else:
f[i + 1][c] = min(f[i][c], f[i + 1][c - x] + 1)
ans = f[n][amount]
return ans if ans < inf else -1
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int n = coins.size(), f[n + 1][amount + 1];
memset(f, 0x3f, sizeof f);
f[0][0] = 0;
for (int i = 0; i < n; i ++ )
for (int c = 0; c <= amount; c ++ )
if (c < coins[i]) f[i + 1][c] = f[i][c];
else f[i + 1][c] = min(f[i][c], f[i + 1][c - coins[i]] + 1);
int ans = f[n][amount];
return ans < 0x3f3f3f3f ? ans : -1;
}
};
解法三:使用滚动数组进行空间优化
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
n = len(coins)
f = [[inf] * (amount + 1) for _ in range(2)]
f[0][0] = 0
for i, x in enumerate(coins):
for c in range(amount + 1):
if c < x:
f[(i + 1) % 2][c] = f[i % 2][c]
else:
f[(i + 1) % 2][c] = min(f[i % 2][c], f[(i + 1) % 2][c - x] + 1)
ans = f[n % 2][amount]
return ans if ans < inf else -1
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int n = coins.size(), f[2][amount + 1];
memset(f, 0x3f, sizeof f);
f[0][0] = 0;
for (int i = 0; i < n; i ++ )
for (int c = 0; c <= amount; c ++ )
if (c < coins[i]) f[(i + 1) % 2][c] = f[i % 2][c];
else f[(i + 1) % 2][c] = min(f[i % 2][c], f[(i + 1) % 2][c - coins[i]] + 1);
int ans = f[n % 2][amount];
return ans < 0x3f3f3f3f ? ans : -1;
}
};
解法四:使用一个数组进行优化
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
f = [0] + [inf] * amount
for x in coins:
for c in range(x, amount + 1):
f[c] = min(f[c], f[c - x] + 1)
ans = f[amount]
return ans if ans < inf else -1
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int f[amount + 1];
memset(f, 0x3f, sizeof f);
f[0] = 0;
for (int x: coins)
for (int c = x; c <= amount; c ++ )
f[c] = min(f[c], f[c - x] + 1);
int ans = f[amount];
return ans < 0x3f3f3f3f ? ans : -1;
}
};
Leetcode 2915
class Solution:
def lengthOfLongestSubsequence(self, nums: List[int], target: int) -> int:
f = [0] + [-inf] * target
s = 0
for x in nums:
s = min(s + x, target)
for j in range(s, x - 1, - 1):
f[j] = max(f[j], f[j - x] + 1)
return f[-1] if f[-1] > 0 else -1
class Solution {
public:
int lengthOfLongestSubsequence(vector<int>& nums, int target) {
vector<int> f(target + 1, INT_MIN);
f[0] = 0;
int s = 0;
for (int x: nums) {
s = min(s + x, target);
for (int j = s; j >= x; j -- )
f[j] = max(f[j], f[j - x] + 1);
}
return f[target] > 0 ? f[target] : -1;
}
};
Leetcode 1143
解法一:记忆化搜索
class Solution:
def longestCommonSubsequence(self, s: str, t: str) -> int:
n, m = len(s), len(t)
@cache
def dfs(i, j):
if i < 0 or j < 0:
return 0
if s[i] == t[j]:
return dfs(i - 1, j - 1) + 1
return max(dfs(i - 1, j), dfs(i, j - 1));
return dfs(n - 1, m - 1)
class Solution {
public:
int longestCommonSubsequence(string s, string t) {
int n = s.size(), m = t.size();
int cache[n][m];
memset(cache, -1, sizeof cache);
function<int(int, int)> dfs=[&](int i, int j)->int {
if (i < 0 || j < 0) return 0;
int &res = cache[i][j];
if (res != -1) return res;
if (s[i] == t[j]) {
res = dfs(i - 1, j - 1) + 1;
return res;
}
res = max(dfs(i - 1, j), dfs(i, j - 1));
return res;
};
return dfs(n - 1, m - 1);
}
};
解法二:递推
class Solution:
def longestCommonSubsequence(self, s: str, t: str) -> int:
n, m = len(s), len(t)
f = [[0] * (m + 1) for _ in range(n + 1)]
for i, x in enumerate(s):
for j, y in enumerate(t):
if x == y:
f[i + 1][j + 1] = f[i][j] + 1
else:
f[i + 1][j + 1] = max(f[i + 1][j], f[i][j + 1])
return f[n][m]
class Solution {
public:
int longestCommonSubsequence(string s, string t) {
int n = s.size(), m = t.size();
int f[n + 1][m + 1];
memset(f, 0, sizeof f);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
f[i + 1][j + 1] = s[i] == t[j] ? f[i][j] + 1 : max(f[i + 1][j], f[i][j + 1]);
return f[n][m];
}
};
解法三:滚动数组
class Solution:
def longestCommonSubsequence(self, s: str, t: str) -> int:
n, m = len(s), len(t)
f = [[0] * (m + 1) for _ in range(2)]
for i, x in enumerate(s):
for j, y in enumerate(t):
if x == y:
f[(i + 1) % 2][j + 1] = f[i % 2][j] + 1
else:
f[(i + 1) % 2][j + 1] = max(f[(i + 1) % 2][j], f[i % 2][j + 1])
return f[n % 2][m]
class Solution {
public:
int longestCommonSubsequence(string s, string t) {
int n = s.size(), m = t.size();
int f[2][m + 1];
memset(f, 0, sizeof f);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
f[(i + 1) % 2][j + 1] = s[i] == t[j] ? f[i % 2][j] + 1 : max(f[(i + 1) % 2][j], f[i % 2][j + 1]);
return f[n % 2][m];
}
};
解法四:一个数组
class Solution:
def longestCommonSubsequence(self, s: str, t: str) -> int:
f = [0] * (len(t) + 1)
for x in s:
pre = 0
for j, y in enumerate(t):
tmp = f[j + 1]
f[j + 1] = pre + 1 if x == y else max(f[j + 1], f[j])
pre = tmp
return f[-1]
class Solution {
public:
int longestCommonSubsequence(string s, string t) {
int m = t.length(), f[m + 1];
memset(f, 0, sizeof f);
for (char x: s)
for (int j = 0, pre = 0; j < m; j ++ ) {
int tmp = f[j + 1];
f[j + 1] = x == t[j] ? pre + 1 : max(f[j + 1], f[j]);
pre = tmp;
}
return f[m];
}
};
Leetcode 72
解法一:记忆化搜索
class Solution:
def minDistance(self, s: str, t: str) -> int:
n, m = len(s), len(t)
@cache
def dfs(i, j):
if i < 0: return j + 1
if j < 0: return i + 1
if s[i] == t[j]: return dfs(i - 1, j - 1)
return min(dfs(i - 1, j), dfs(i, j - 1), dfs(i - 1, j - 1)) + 1
return dfs(n - 1, m - 1)
class Solution {
public:
int minDistance(string s, string t) {
int n = s.length(), m = t.length();
int cache[n + 1][m + 1];
memset(cache, -1, sizeof cache);
function<int(int, int)> dfs = [&](int i, int j)->int {
if (i < 0) return j + 1;
if (j < 0) return i + 1;
int &res = cache[i][j];
if (res != -1) return res;
if (s[i] == t[j]) {
res = dfs(i - 1, j - 1);
return res;
}
res = min(min(dfs(i - 1, j), dfs(i, j - 1)), dfs(i - 1, j - 1)) + 1;
return res;
};
return dfs(n - 1, m - 1);
}
};
解法二:递推
class Solution:
def minDistance(self, s: str, t: str) -> int:
n, m = len(s), len(t)
f = [[0] * (m + 1) for _ in range(n + 1)]
f[0] = list(range(m + 1)) # 当i<0的时候
for i, x in enumerate(s):
f[i + 1][0] = i + 1 # 当j<0的时候
for j, y in enumerate(t):
f[i + 1][j + 1] = f[i][j] if x == y else min(f[i][j + 1], f[i + 1][j], f[i][j]) + 1
return f[n][m]
class Solution {
public:
int minDistance(string s, string t) {
int n = s.length(), m = t.length();
int f[n + 1][m + 1];
for (int j = 0; j <= m; j ++ ) f[0][j] = j;
for (int i = 0; i < n; i ++ ) {
f[i + 1][0] = i + 1;
for (int j = 0; j < m; j ++ )
f[i + 1][j + 1] = s[i] == t[j] ? f[i][j] : min(min(f[i][j + 1], f[i + 1][j]), f[i][j]) + 1;
}
return f[n][m];
}
};
滚动数组
class Solution:
def minDistance(self, s: str, t: str) -> int:
n, m = len(s), len(t)
f = [list(range(m + 1)), [0] * (m + 1)]
for i, x in enumerate(s):
f[(i + 1) % 2][0] = i + 1 # 当j<0的时候
for j, y in enumerate(t):
f[(i + 1) % 2][j + 1] = f[i % 2][j] if x == y else min(f[i % 2][j + 1], f[(i + 1) % 2][j], f[i % 2][j]) + 1
return f[n % 2][m]
class Solution {
public:
int minDistance(string s, string t) {
int n = s.length(), m = t.length();
int f[2][m + 1];
for (int j = 0; j <= m; j ++ ) f[0][j] = j;
for (int i = 0; i < n; i ++ ) {
f[(i + 1) % 2][0] = i + 1;
for (int j = 0; j < m; j ++ )
f[(i + 1) % 2][j + 1] = s[i] == t[j] ? f[i % 2][j] : min(min(f[i % 2][j + 1], f[(i + 1) % 2][j]), f[i % 2][j]) + 1;
}
return f[n % 2][m];
}
};
解法四:一个数组
class Solution:
def minDistance(self, s: str, t: str) -> int:
f = list(range(len(t) + 1))
for x in s:
pre = f[0]
f[0] += 1
for j, y in enumerate(t):
tmp = f[j + 1]
f[j + 1] = pre if x == y else min(f[j + 1], f[j], pre) + 1
pre = tmp
return f[-1]
class Solution {
public:
int minDistance(string s, string t) {
int m = t.length(), f[m + 1];
iota(f, f + m + 1, 0);
for (char x: s) {
int pre = f[0];
f[0] ++ ;
for (int j = 0; j < m; j ++ ) {
int tmp = f[j + 1];
f[j + 1] = x == t[j] ? pre : min(min(f[j + 1], f[j]), pre) + 1;
pre = tmp;
}
}
return f[m];
}
};
LIS 问题的基础解法是时间复杂度为 O ( n 2 ) O(n^2) O(n2) 的 DP 解法,优化的思路有两个:
- 时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn) 的贪心+二分的解法
- 基于值域的树状数组/线段树解法
Leetcode 300
思路一:动态规划
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
@cache
def dfs(i: int)->int:
res = 0
for j in range(i):
if (nums[j] < nums[i]):
res = max(res, dfs(j))
return res + 1
return max(dfs(i) for i in range(len(nums)))
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size(), cache[n];
memset(cache, 0, sizeof cache);
function<int(int)> dfs = [&](int i)->int {
int &res = cache[i];
if (res) return res;
for (int j = 0; j < i; j ++ )
if (nums[j] < nums[i])
res = max(res, dfs(j));
return ++ res;
};
int ans = 0;
for (int i = 0; i < n; i ++ )
ans = max(ans, dfs(i));
return ans;
}
};
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
f = [0] * len(nums)
for i, x in enumerate(nums):
for j, y in enumerate(nums[:i]):
if x > y:
f[i] = max(f[i], f[j]);
f[i] += 1
return max(f)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size(), f[n];
for (int i = 0; i < n; i ++ ) {
f[i] = 0;
for (int j = 0; j < i; j ++ )
if (nums[i] > nums[j])
f[i] = max(f[i], f[j]);
f[i] ++ ;
}
return *max_element(f, f + n);
}
};
思路二:贪心 + 二分
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
g = []
for x in nums:
j = bisect_left(g, x)
if j == len(g): g.append(x)
else: g[j] = x
return len(g)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> g;
for (int x: nums) {
auto it = lower_bound(g.begin(), g.end(), x);
if (it == g.end()) g.push_back(x);
else *it = x;
}
return g.size();
}
};
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
空间复杂度: O ( n ) O(n) O(n)
解法二:原地修改
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
ng = 0
for x in nums:
j = bisect_left(nums, x, 0, ng)
nums[j] = x
if j == ng: ng += 1
return ng
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
auto end = nums.begin();
for (int x: nums) {
auto it = lower_bound(nums.begin(), end, x);
*it = x;
if (it == end) end ++ ;
}
return end - nums.begin();
}
};
Leetcode 2407
class Solution:
def lengthOfLIS(self, nums: List[int], k: int) -> int:
u = max(nums)
mx = [0] * (4 * u)
def modify(o: int, l: int, r: int, i: int, val: int)->None:
if l == r:
mx[o] = val
return
m = (l + r) // 2
if i <= m: modify(o * 2, l, m, i, val)
else: modify(o * 2 + 1, m + 1, r, i, val)
mx[o] = max(mx[o * 2], mx[o * 2 + 1])
def query(o: int, l: int, r: int, L: int, R: int)->int:
if L <= l and r <= R: return mx[o]
res = 0
m = (l + r) // 2
if L <= m: res = query(o * 2, l, m, L, R)
if R > m: res = max(res, query(o * 2 + 1, m + 1, r, L, R))
return res
for x in nums:
if x == 1:
modify(1, 1, u, 1, 1)
else:
res = 1 + query(1, 1, u, max(x - k, 1), x - 1)
modify(1, 1, u, x, res)
return mx[1]
class Solution {
vector<int> mx;
void modify(int o, int l, int r, int i, int val) {
if (l == r) {
mx[o] = val;
return;
}
int m = (l + r) / 2;
if (i <= m) modify(o * 2, l, m, i, val);
else modify(o * 2 + 1, m + 1, r, i, val);
mx[o] = max(mx[o * 2], mx[o * 2 + 1]);
}
int query(int o, int l, int r, int L, int R) {
if (L <= l && r <= R) return mx[o];
int res = 0, m = (l + r) / 2;
if (L <= m) res = query(o * 2, l, m, L, R);
if (R > m) res = max(res, query(o * 2 + 1, m + 1, r, L, R));
return res;
}
public:
int lengthOfLIS(vector<int>& nums, int k) {
int u = *max_element(nums.begin(), nums.end());
mx.resize(u * 4);
for (int x: nums)
if (x == 1) modify(1, 1, u, 1, 1);
else {
int res = 1 + query(1, 1, u, max(x - k, 1), x - 1);
modify(1, 1, u, x, res);
}
return mx[1];
}
};
Leetcode 1626
解法一:排序+动态规划
class Solution:
def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
a = sorted(zip(scores, ages))
f = [0] * len(a)
for i, (score, age) in enumerate(a):
for j in range(i):
if a[j][1] <= age:
f[i] = max(f[i], f[j])
f[i] += score
return max(f)
class Solution {
public:
int bestTeamScore(vector<int>& scores, vector<int>& ages) {
int n = scores.size();
pair<int, int> a[n];
for (int i = 0; i < n; i ++ )
a[i] = {scores[i], ages[i]};
sort(a, a + n);
int f[n];
memset(f, 0, sizeof f);
for (int i = 0; i < n; i ++ ) {
for (int j = 0; j < i; j ++ )
if (a[j].second <= a[i].second)
f[i] = max(f[i], f[j]);
f[i] += a[i].first;
}
return *max_element(f, f + n);
}
};
解法二:基于值域运算
class Solution:
def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
max_sum = [0] * (max(ages) + 1)
for score, age in sorted(zip(scores, ages)):
max_sum[age] = max(max_sum[:age + 1]) + score
return max(max_sum)
class Solution {
public:
int bestTeamScore(vector<int>& scores, vector<int>& ages) {
int n = scores.size();
pair<int, int> a[n];
for (int i = 0; i < n; i ++ )
a[i] = {scores[i], ages[i]};
sort(a, a + n);
int u = *max_element(ages.begin(), ages.end());
int max_sum[u + 1]; memset(max_sum, 0, sizeof max_sum);
for (auto &[score, age] : a)
max_sum[age] = *max_element(max_sum, max_sum + age + 1) + score;
return *max_element(max_sum, max_sum + u + 1);
}
};
解法三:树状数组优化
class Solution:
def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
u = max(ages)
t = [0] * (u + 1)
def query(i: int)->int:
mx = 0
while i:
mx = max(mx, t[i])
i &= i - 1
return mx
def update(i: int, mx: int)->None:
while i < len(t):
t[i] = max(t[i], mx)
i += i & -i
for score, age in sorted(zip(scores, ages)):
update(age, query(age) + score)
return query(u)
class Solution {
static constexpr int MX = 1000;
int t[MX + 1];
int query(int i) {
int mx = 0;
for (; i; i &= i - 1) mx = max(mx, t[i]);
return mx;
}
void update(int i, int mx) {
for (; i <= MX; i += i & -i)
t[i] = max(t[i], mx);
}
public:
int bestTeamScore(vector<int>& scores, vector<int>& ages) {
int n = scores.size();
pair<int, int> a[n];
for (int i = 0; i < n; i ++ )
a[i] = {scores[i], ages[i]};
sort(a, a + n);
for (auto &[score, age] : a)
update(age, query(age) + score);
return query(MX);
}
};