力扣 411周赛

统计满足K约束的子字符串数量 I

给你一个 二进制 字符串 s 和一个整数 k。
如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束:
字符串中 0 的数量最多为 k。
字符串中 1 的数量最多为 k。
返回一个整数,表示 s 的所有满足 k 约束 的子字符串的数量。
 
输入:s = "10101", k = 1
输出:12
解释:s 的所有子字符串中,除了 "1010"、"10101" 和 "0101" 外,其余子字符串都满足 k 约束。

提示:
1 <= s.length <= 50
1 <= k <= s.length
s[i] 是 '0' 或 '1'。

分析问题:

  1. 长度不大于K的字符串肯定符合条件
  2. 字符串的长度最大为50,复杂度可以为 l o g ( n 3 ) log(n^3) log(n3)
    我想到的方法是:用前缀和做,表示 0 - i (假设当前位置为i) 分别有多少个0和1,最后,只需要枚举长度大于k的字符串的左右边界加上长度不大于k的字符串的个数 ( n + n − k + 1 ) ∗ ( k − 1 ) / 2 (n + n-k+1) * (k - 1) / 2 (n+n−k+1)∗(k−1)/2 。
java 复制代码
const int N = 60;
class Solution {
public:
    
    int cnt[N];
    int countKConstraintSubstrings(string s, int k) {
        int n = s.size();
        int ans = 0;
        int t = min(n, k);
        ans += (n + n - t + 1) * t / 2;
        for (int i = 1; i <= n; i++) {
            if (s[i-1] == '1') cnt[i] = 1;
            cnt[i] += cnt[i - 1];
        }
        for (int i = 0; i < n; i++) {
            for (int j = i + k + 1; j <= n; j++) {
                int t = cnt[j] - cnt[i];
                if (t <= k || j - i - t <= k) ans++;
            }
        }
        return ans;
    }
};

超级饮料的最大强化能量

来自未来的体育科学家给你两个整数数组 energyDrinkA 和 energyDrinkB,数组长度都等于 n。这两个数组分别代表 A、B 两种不同能量饮料每小时所能提供的强化能量。
你需要每小时饮用一种能量饮料来 最大化 你的总强化能量。然而,如果从一种能量饮料切换到另一种,你需要等待一小时来梳理身体的能量体系(在那个小时里你将不会获得任何强化能量)。
返回在接下来的 n 小时内你能获得的 最大 总强化能量。
注意 你可以选择从饮用任意一种能量饮料开始。

示例 1:
输入:energyDrinkA = [1,3,1], energyDrinkB = [3,1,1]
输出:5
解释:
要想获得 5 点强化能量,需要选择只饮用能量饮料 A(或者只饮用 B)。
示例 2:
输入:energyDrinkA = [4,1,1], energyDrinkB = [1,1,3]
输出:7
解释:
第一个小时饮用能量饮料 A。
切换到能量饮料 B ,在第二个小时无法获得强化能量。
第三个小时饮用能量饮料 B ,并获得强化能量。
 
提示:
n == energyDrinkA.length == energyDrinkB.length
3 <= n <= 105
1 <= energyDrinkA[i], energyDrinkB[i] <= 105

解题思路:用动态规划来做。

公式( f[i][0] 表示i位置不喝饮料,f[i][1]表示i位置喝 a 饮料,f[i][2] 表示i位置喝 b 饮料 ):
f [ i ] [ 0 ] = m a x ( f [ i − 1 ] [ 0 ] , f [ i − 1 ] [ 1 ] , f [ i − 1 ] [ 2 ] ) f[i][0] = max(f[i-1][0], f[i-1][1], f[i-1][2]) f[i][0]=max(f[i−1][0],f[i−1][1],f[i−1][2])
f [ i ] [ 1 ] = m a x ( f [ i − 1 ] [ 0 ] , f [ i − 1 ] [ 1 ] ) + a [ i ] f[i][1] = max(f[i-1][0], f[i-1][1]) + a[i] f[i][1]=max(f[i−1][0],f[i−1][1])+a[i]
f [ i ] [ 2 ] = m a x ( f [ i − 1 ] [ 0 ] , f [ i − 1 ] [ 2 ] ) + b [ i ] f[i][2] = max(f[i-1][0], f[i-1][2]) + b[i] f[i][2]=max(f[i−1][0],f[i−1][2])+b[i]

找出最大的N位K回文数

我分析的方法:用9填充(n+1)/2位数,从后往前一次递减遍历每位数,从后往前遍历这个数添加到这个数的末尾形成回文数直到可以被k整除。

判断是否是k的倍数,可以每次加一个数时都对加和取余,不影响结果。

这个方法会超时

java 复制代码
const int N = 1e5 +10;
class Solution {
public:
    int n, k;
    char str[N];
    string ans;
    void dfs(int pos) {
        if(ans.size()) return;
        int t = (n + 1) >> 1;
        if (pos == t) {
            long long p = 0;
            for (int i = 0; i < n; i++) {
                p = (p * 10 % k + str[i < t ? i : (n / 2 - 1 - i % t)] - '0') % k;
              //  cout << str[i < t ? i : (n / 2 - 1 - i % t)];
            }
          //  cout << endl;
          //  cout << "p=" << p <<endl;
            if (!p) {
                ans = "";
                for(int i=0; i < n; i++) ans += str[i < t ? i : (n / 2 - 1 - i % t)];
                return;
            }
            return;
        }
        for (char c = '9'; c >= '0'; c--) {
            str[pos] = c;
            dfs(pos + 1);
        }
    }
    string largestPalindrome(int n, int k) {
        this->n = n;
        this->k = k;
        dfs(0);
        return ans;
    }
};
相关推荐
是小Y啦几秒前
leetcode 106.从中序与后续遍历序列构造二叉树
数据结构·算法·leetcode
LyaJpunov几秒前
C++中move和forword的区别
开发语言·c++
程序猿练习生5 分钟前
C++速通LeetCode中等第9题-合并区间
开发语言·c++·leetcode
liuyang-neu10 分钟前
力扣 42.接雨水
java·算法·leetcode
z千鑫14 分钟前
【人工智能】如何利用AI轻松将java,c++等代码转换为Python语言?程序员必读
java·c++·人工智能·gpt·agent·ai编程·ai工具
一名路过的小码农15 分钟前
C/C++动态库函数导出 windows
c语言·开发语言·c++
y_dd18 分钟前
【machine learning-12-多元线性回归】
算法·机器学习·线性回归
m0_6312704018 分钟前
标准c语言(一)
c语言·开发语言·算法
万河归海42818 分钟前
C语言——二分法搜索数组中特定元素并返回下标
c语言·开发语言·数据结构·经验分享·笔记·算法·visualstudio
小周的C语言学习笔记22 分钟前
鹏哥C语言36-37---循环/分支语句练习(折半查找算法)
c语言·算法·visual studio