LeetCode双周赛111

LeetCode双周赛111

A题

B题

C题

题意:数组元素下标被放到3个容器中,要求第二个容器中的最小值大于第一个容器的最大值,第三个容器的最小值大于第二个元素的最大值。(容器可以为空),求最小的操作变换次数。

思路:本质上就是数组的元素要保证是单调递增的,每个元素都可以选择变和不变,那么就转变成了01背包问题,代码如下:

public int minimumOperations(List<Integer> nums) {
    var dp = new int[nums.size() + 1][4];
    for (int i = 1; i <= nums.size(); i++) {
        for (int k = 1; k <= 3; k++) {
            dp[i][k] = Integer.MAX_VALUE;
            int cnt = nums.get(i - 1) == k ? 0 : 1;
            for (int j = 1; j <= k; j++) {
                dp[i][k] = Math.min(dp[i][k], dp[i - 1][j]);
            }
            dp[i][k] += cnt;
        }
    }
    return Math.min(dp[nums.size()][1], Math.min(dp[nums.size()][2], dp[nums.size()][3]));
}

D题

题意:给定一个正整数low,high和k,求出[low, high]范围内的美丽数目,美丽数目定义为偶数数位等于奇数数位,并且能被k整数。

思路:这种题型一看就是要用数位dp,可以想到我们构造的dp数组应该是dp[len][k][diff],len表示长度,k表示余数,diff表示奇数数位和偶数数位的差和。

我们使用递归的做法求出dp数组。

dfs(len, val, isLimit, isNum, s, dp, k, diff)

len代表当前遍历的长度,val代表余数,isLimit表示当前需要填的数字是否受到限制,isNum表示当前是否已经填了数字。

如果isLimit表示为true,说明后续数字会受到限制,如果

isNum为false表示当前位可以无需填写,为true表示当前位必须填写数字,并且dp可以更新。

public int numberOfBeautifulIntegers(int low, int high, int k) {
    return calc(String.valueOf(high), k) - calc(String.valueOf(low - 1), k);

}

private int calc(String s, int k) {
    char[] chars = s.toCharArray();
    int len = chars.length;
    var dp = new int[len][k][(chars.length << 1) + 1];
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < k; j++) {
            Arrays.fill(dp[i][j], -1);
        }
    }
    int diff = chars.length;
    return dfs(0, 0, true, false, chars, dp, k, diff);
}

private int dfs(int len, int val, boolean isLimit, boolean isNum, char[] s, int[][][] dp, int k, int diff) {
    if (len == s.length) {
        return isNum && val == 0 && diff == s.length ? 1 : 0;
    }
    if (!isLimit && isNum && dp[len][val][diff] != -1) {
        return dp[len][val][diff];
    }
    int res = isNum ? 0 : dfs(len + 1, val, false, false, s, dp, k, diff);
    int bit = isLimit ? s[len] - '0' : 9;
    for (int j = isNum ? 0 : 1; j <= bit; j++) {
        res += dfs(len + 1, (val * 10 + j) % k, isLimit && j == bit, true, s, dp, k, diff + ((j & 1) << 1) - 1);
    }
    if (!isLimit && isNum) {
        dp[len][val][diff] = res;
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值