难度简单0
给你一个整数数组 nums
,如果它是数组 base[n]
的一个排列,我们称它是个 好 数组。
base[n] = [1, 2, ..., n - 1, n, n]
(换句话说,它是一个长度为 n + 1
且包含 1
到 n - 1
恰好各一次,包含 n
两次的一个数组)。比方说,base[1] = [1, 1]
,base[3] = [1, 2, 3, 3]
。
如果数组是一个好数组,请你返回 true
,否则返回 false
。
**注意:**数组的排列是这些数字按任意顺序排布后重新得到的数组。
示例 1:
输入:nums = [2, 1, 3]
输出:false
解释:因为数组的最大元素是 3 ,唯一可以构成这个数组的 base[n] 对应的 n = 3 。但是 base[3] 有 4 个元素,但数组 nums 只有 3 个元素,所以无法得到 base[3] = [1, 2, 3, 3] 的排列,所以答案为 false 。
示例 2:
输入:nums = [1, 3, 3, 2]
输出:true
解释:因为数组的最大元素是 3 ,唯一可以构成这个数组的 base[n] 对应的 n = 3 ,可以看出数组是 base[3] = [1, 2, 3, 3] 的一个排列(交换 nums 中第二个和第四个元素)。所以答案为 true 。
示例 3:
输入:nums = [1, 1]
输出:true
解释:因为数组的最大元素是 1 ,唯一可以构成这个数组的 base[n] 对应的 n = 1,可以看出数组是 base[1] = [1, 1] 的一个排列。所以答案为 true 。
示例 4:
输入:nums = [3, 4, 4, 1, 2, 1]
输出:false
解释:因为数组的最大元素是 4 ,唯一可以构成这个数组的 base[n] 对应的 n = 4 。但是 base[n] 有 5 个元素而 nums 有 6 个元素。所以答案为 false 。
提示:
1 <= nums.length <= 100
1 <= num[i] <= 200
class Solution {
public boolean isGood(int[] nums) {
int n = nums.length;
int[] vis = new int[n];
for(int num : nums){
if(num >= n) return false;
vis[num] += 1;
}
for(int i = 1; i < n-1; i++)
if(vis[i] != 1) return false;
return vis[n-1] == 2;
}
}
class Solution {
public boolean isGood(int[] nums) {
int n = nums.length - 1;
int[] cnt = new int[n+1];
for(int v : nums){
if(v > n || (v < n && cnt[v] > 0) || (v == n && cnt[v] > 1))
return false;
cnt[v] += 1;
}
return true;
}
}
难度中等1
给你一个下标从 0 开始的字符串 s
,将 s
中的元素重新 排列 得到新的字符串 t
,它满足:
0 <= i < s.length
的下标 i
处的 s[i]
是个辅音字母,那么 t[i] = s[i]
。0 <= i < j < s.length
的下标 i
和 j
,如果 s[i]
和 s[j]
都是元音字母,那么 t[i]
的 ASCII 值不能大于 t[j]
的 ASCII 值。请你返回结果字母串。
元音字母为 'a'
,'e'
,'i'
,'o'
和 'u'
,它们可能是小写字母也可能是大写字母,辅音字母是除了这 5 个字母以外的所有字母。
示例 1:
输入:s = "lEetcOde"
输出:"lEOtcede"
解释:'E' ,'O' 和 'e' 是 s 中的元音字母,'l' ,'t' ,'c' 和 'd' 是所有的辅音。将元音字母按照 ASCII 值排序,辅音字母留在原地。
示例 2:
输入:s = "lYmpH"
输出:"lYmpH"
解释:s 中没有元音字母(s 中都为辅音字母),所以我们返回 "lYmpH" 。
提示:
1 <= s.length <= 105
s
只包含英语字母表中的 大写 和 小写 字母。class Solution {
public String sortVowels(String s) {
Set<Character> set = new HashSet<>();
set.add('a');set.add('e');set.add('i');set.add('o');set.add('u');
set.add('A');set.add('E');set.add('I');set.add('O');set.add('U');
int n = s.length();
StringBuilder sb = new StringBuilder();
boolean[] isval = new boolean[n];
for(int i = 0; i < n; i++){
if(set.contains(s.charAt(i))){
sb.append(s.charAt(i));
isval[i] = true;
}
}
char[] ns = sb.toString().toCharArray();
Arrays.sort(ns);
int idx = 0;
sb = new StringBuilder();
for(int i = 0; i < n; i++){
if(isval[i]){
sb.append(ns[idx++]);
}else
sb.append(s.charAt(i));
}
return sb.toString();
}
}
难度中等1
给你一个下标从 0 开始的整数数组 nums
和一个正整数 x
。
你 一开始 在数组的位置 0
处,你可以按照下述规则访问数组中的其他位置:
i
,那么你可以移动到满足 i < j
的 任意 位置 j
。i
,你可以获得分数 nums[i]
。i
移动到位置 j
且 nums[i]
和 nums[j]
的 奇偶性 不同,那么你将失去分数 x
。请你返回你能得到的 最大 得分之和。
注意 ,你一开始的分数为 nums[0]
。
示例 1:
输入:nums = [2,3,6,1,9,2], x = 5
输出:13
解释:我们可以按顺序访问数组中的位置:0 -> 2 -> 3 -> 4 。
对应位置的值为 2 ,6 ,1 和 9 。因为 6 和 1 的奇偶性不同,所以下标从 2 -> 3 让你失去 x = 5 分。
总得分为:2 + 6 + 1 + 9 - 5 = 13 。
示例 2:
输入:nums = [2,4,6,8], x = 3
输出:20
解释:数组中的所有元素奇偶性都一样,所以我们可以将每个元素都访问一次,而且不会失去任何分数。
总得分为:2 + 4 + 6 + 8 = 20 。
提示:
2 <= nums.length <= 105
1 <= nums[i], x <= 106
class Solution:
def maxScore(self, nums: List[int], x: int) -> int:
n = len(nums)
@cache
def dfs(i, j: int) -> int:
if i == n:
return 0
v = nums[i]
# 选
res = dfs(i+1, v%2) + v
# 如果v 的奇偶性与上一个选的不同,则需要减去x
if v%2 != j:
res -= x
# 不选,直接跳过
res = max(res, dfs(i+1, j))
return res
return dfs(1, nums[0]%2) + nums[0]
dp[i][0]
表示前i个最后停到偶数的最大分数
dp[i][1]
表示前i个最后停到奇数位置的最大分数
则有如果nums[i]
是奇数时
dp[i][1]
考虑前i-1个最后在奇数位置转移过来,和从偶数转移过来的情况,其中偶数转移过来需要扣分.
因为当前位为奇数,则对dp[i][0]
无影响,其等于dp[i-1
][0]
dp[i][1] = max(dp[i-1][1] + nums[i] , dp[i - 1][0] + nums[i] - x)
dp[i][0] = dp[i-1][0]
反之考虑当前为偶数时
dp[i][0]
考虑前面从偶数过来和奇数过来的情况,奇数需要扣分
dp[i][1]
不受影响
dp[i][0] = max(dp[i-1][0] + nums[i] , dp[i - 1][1] + nums[i] - x)
dp[i][1] = dp[i-1][1]
常规状态压缩一下
class Solution:
def maxScore(self, nums: List[int], x: int) -> int:
n = len(nums)
f = [[-inf] * 2 for _ in range(n)]
f[0][nums[0] & 1] = nums[0]
f[0][1 - (nums[0] & 1)] = -x # <= nums[0] - x即可
for i in range(1, n):
f[i][nums[i] & 1] = max(f[i-1][nums[i] & 1] + nums[i], f[i-1][1 - (nums[i] & 1)] + nums[i] - x)
f[i][1 - (nums[i] & 1)] = f[i-1][1 - (nums[i] & 1)]
return max(f[n-1][0], f[n-1][1])
难度中等0
给你两个 正 整数 n
和 x
。
请你返回将 n
表示成一些 互不相同 正整数的 x
次幂之和的方案数。换句话说,你需要返回互不相同整数 [n1, n2, ..., nk]
的集合数目,满足 n = n1x + n2x + ... + nkx
。
由于答案可能非常大,请你将它对 109 + 7
取余后返回。
比方说,n = 160
且 x = 3
,一个表示 n
的方法是 n = 23 + 33 + 53
。
示例 1:
输入:n = 10, x = 2
输出:1
解释:我们可以将 n 表示为:n = 32 + 12 = 10 。
这是唯一将 10 表达成不同整数 2 次方之和的方案。
示例 2:
输入:n = 4, x = 1
输出:2
解释:我们可以将 n 按以下方案表示:
- n = 41 = 4 。
- n = 31 + 11 = 4 。
提示:
1 <= n <= 300
1 <= x <= 5
在这种方法中,我们首先检查数字本身是否是任何num power的幂。如果是,则返回方式为1,如果不是,则递归检查num幂+(num + 1)幂。
class Solution:
def numberOfWays(self, n: int, x: int) -> int:
mod = int(10 ** 9 + 7)
@cache
def f(n, p, val: int) -> int:
c = n - pow(val, p)
if c == 0:
return 1
elif c < 0:
return 0
else:
t = val + 1
return (f(c, p, t) + f(n, p, t)) % mod
return f(n, x, 1)
https://leetcode.cn/problems/ways-to-express-an-integer-as-sum-of-powers/solution/0-1-bei-bao-mo-ban-ti-by-endlesscheng-ap09/
背包容量是 n,有若干个物品(n^x, n^x, n^x
),恰好装满0-1背包的方案数
class Solution {
public int numberOfWays(int n, int x) {
int[] f = new int[n+1];
f[0] = 1;
for(int i = 1, p; (p = (int)Math.pow(i, x)) <= n; i++){
for(int j = n; j >= p; j--){
f[j] += f[j-p];
f[j] %= 1000000007;
}
}
return f[n];
}
}
相似题目
动态规划,什么时候用枚举选哪个?什么时候用选或不选?
nums[i]
,只需要抽象问题的要求。枚举选哪个:适用于需要完全知道子序列相邻两数的信息。
选或不选:适用于 ① 子序列相邻数字无关、② 子序列相邻数字弱关联(奇偶性或只需要知道 0 和 1的信息)