力扣每日一题合集

3211. 生成不含相邻零的二进制字符串 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
   vector<string> validStrings(int n) 
   {
       vector<string> ans;
       ans.emplace_back("0");
       ans.emplace_back("1");
       for(int i = 1; i < n; i++)
       {
            int m = ans.size();
            for(int j = 0; j < m; j++)
            {
                auto x = ans[j].back();
                if('1' == x)ans.emplace_back(ans[j] + "0");
                ans[j] += '1';
            }
       }
       return ans;
   }
};

1016. 子串能表示从 1 到 N 数字的二进制串 - 力扣(LeetCode)

解一:暴力(bitset模板)

cpp 复制代码
class Solution {
public:
    bool queryString(string s, int n) 
    {
        for(int i = 1;i <= n; i++)
        {
            auto str = bitset<32>(i).to_string();
            str = str.substr(str.find('1'));
            if(s.find(str) == s.npos)return false;
        }
        return true;
    }
};

解二:哈希表

cpp 复制代码
class Solution {
public:
    bool queryString(string s, int n)
    {
        unordered_set<int>ans;
        for(int i = 0;i < s.size(); i++)
        {
            int x = s[i] ^ 48;
            if(!x)continue;
            for(int j = i + 1;x <= n;j++)
            {//提问1:为什么是j = i + 1 ??? 
                ans.insert(x);
                x = (x << 1) | (s[j] ^ 48);//提问二:这样赋值的意义?
                if(j == s.size() )break;
            }
        }
        return ans.size() == n;
    }
};

解三:滑动窗口 + 哈希表 + 数学

分析:

1:列表

|----|------|
| 1 | 1 |
| 2 | 10 |
| 3 | 11 |
| 4 | 100 |
| 5 | 101 |
| 6 | 110 |
| 7 | 111 |
| 8 | 1000 |
| 9 | 1001 |
| 10 | 1010 |
| 11 | 1011 |
| 12 | 1100 |
| 13 | 1101 |
| 14 | 1110 |
| 15 | 1111 |

cpp 复制代码
class Solution {
public:
    bool help(const string& s, int bitlen, int min, int max) 
    {
        unordered_set<int> st;
        int t = 0;
        for (int r = 0; r < s.size(); ++r)
        {
            t = (t << 1) + (s[r] ^ 48);
            if (r >= bitlen)
                t -= (s[r - bitlen] ^ 48) << bitlen;
            if (r >= bitlen - 1 && t >= min && t <= max)
                st.insert(t);
        }
        return st.size() == max - min + 1;
    }

    bool queryString(string s, int n) 
    {
        if (n == 1)  return s.find('1') != s.npos;
        int bitlen = 31 - __builtin_clz(n);
        if (s.size() < (1 << (bitlen - 1)) + bitlen - 1 || s.size() < n - (1 << bitlen) + bitlen + 1) return false;
        return help(s, bitlen, 1 << (bitlen - 1), (1 << bitlen) - 1) && help(s, bitlen + 1, 1 << bitlen, n);
    }
};

122. 买卖股票的最佳时机 II - 力扣(LeetCode)

cpp 复制代码
//由于当天买可以当天卖 == >> 每天都更新状态
//状态一:   当前卖亏本 == >> 穿越到昨天卖出 然后买今天(即理解为昨天买了昨天就卖)
//状态二:   当前卖盈利 == >> 卖出 == >> 更新答案
//状态三:   当前卖亏本但是卖出前些天的盈利 == >> 穿越到昨天不卖出,今天卖出 == >> 更新答案
class Solution {
public:
    int maxProfit(vector<int>& prices) 
    {
        int ans = 0;
        int pre = INT_MAX;
        int sell = pre;
        int profit = 0;
        for(auto x : prices)
        {
            if(x > pre)
            {//可以出售
                ans += x - pre;
                profit = x - pre;
                pre = sell = x;
            }
            else
            {//出售亏本
                if(x - sell > profit)
                {
                    ans = ans - profit + x - sell;
                    profit = x - sell;
                }
                else
                {
                    pre = x;
                }
            }
        }
        return ans;
    }
};

307. 区域和检索 - 数组可修改 - 力扣(LeetCode)

cpp 复制代码
int init = []()
{
    cin.tie(0) -> sync_with_stdio(false);
    return 0;
}();

class NumArray {
public:
    NumArray(vector<int>& nums) : sum(nums.size() + 1, 0), num(nums), n(nums.size()) 
    {
        for(int i = 0;i < n;i++)
        add(i + 1,nums[i]);
    }

    int lowbit(int x)
    {
        return x & -x;
    }

    void add(int pos, int val)
    {
        for(; pos <= n; pos += lowbit(pos))
        sum[pos] += val;
    }

    void update(int index, int val) 
    {
        add(index + 1, val - num[index]);
        num[index] = val;
    }
    
    int ask(int x)
    {
        int ans = 0;
        for(; x > 0; x -= lowbit(x))
        ans += sum[x];
        return ans;
    }

    int sumRange(int left, int right) 
    {
        return ask(right + 1) - ask(left);
    }
private:
vector<int>sum;
vector<int>&num;
int n;
};

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray* obj = new NumArray(nums);
 * obj->update(index,val);
 * int param_2 = obj->sumRange(left,right);
 */

354. 俄罗斯套娃信封问题 - 力扣(LeetCode)

示例 1:

复制代码
输入:envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出:3
解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。

示例 2:

复制代码
输入:envelopes = [[1,1],[1,1],[1,1]]
输出:1

提示:

  • 1 <= envelopes.length <= 105
  • envelopes[i].length == 2
  • 1 <= wi, hi <= 105

首先按照朴素的dp思想

先定义每一个信封的状态,无非是选择或者不选择。

int dpn; 选择第i个信封最多可以嵌套的数量.

在按照

cpp 复制代码
  sort(envelopes.begin(),envelopes.end(),[&](auto x, auto y)
        {return x[0] == y[0] ? x[1] < y[1] : x[0] < y[0];});

规则的排序下,可知道

若 第i个信封可以完全包裹上一个信封则进行

cpp 复制代码
                if(envelopes[i][1] > envelopes[j][1] && envelopes[i][0] > envelopes[j][0])
                {
                    dp[i] = max(dp[i], dp[j] + 1);
                }

否则将 dpi置为1

为什么置为1 ?

因为不存在当第i个信封能完全包裹一个信封的情况下会有不选择该信封的ans > 选择该信封的ans

那么可以认为,要么第i个信封能包裹信封,要么将第i个信封作为一个新的开头

可得最初版的线型dp解

cpp 复制代码
class Solution {
public:
    int maxEnvelopes(vector<vector<int>>& envelopes) 
    {
        sort(envelopes.begin(),envelopes.end(),[&](auto x, auto y)
        {return x[0] == y[0] ? x[1] < y[1] : x[0] < y[0];});
        int n = envelopes.size();
        int dp[n];
        memset(dp, 0, sizeof dp);
        dp[0] = 1;
        for(int i = 1; i < n; i++)
        {
            for(int j = i - 1; j >= 0; j--)
            {
                if(envelopes[i][1] > envelopes[j][1] && envelopes[i][0] > envelopes[j][0])
                {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            if(0 == dp[i])dp[i] = 1;
        }
        int ans = 0;
        for(int i = 0; i < n;i++)
        ans = max(ans, dp[i]);
        return ans;
    }
};

以上代码的时间复杂度为排序O(nlogn) + O(n ^ 2)

显然对于 1 <= envelopes.length <= 105 是远远不够的

现在看看核心代码

cpp 复制代码
        for(int i = 1; i < n; i++)
        {
            for(int j = i - 1; j >= 0; j--)
            {
                if(envelopes[i][1] > envelopes[j][1] && envelopes[i][0] > envelopes[j][0])
                {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            if(0 == dp[i])dp[i] = 1;
        }

是不是很像求最长递减子序列?

只不过是先对长or宽排序之后对宽or长序列求最长子序列即可

那我们直接用二分优化求最长子序列的方法做即可

cpp 复制代码
class Solution {
public:
    int maxEnvelopes(vector<vector<int>>& envelopes) 
    {
        sort(envelopes.begin(),envelopes.end(),[&](auto x, auto y)
        {return x[0] == y[0] ? x[1] > y[1] : x[0] < y[0];});
        int n = envelopes.size();
        vector v = {0};
        for(int i = 0; i < n; i++)
        {
            int k = envelopes[i][1];
            if(k > v.back())
            {
                v.emplace_back(k);
            }
            else
            {
                auto it = lower_bound(v.begin(),v.end(),k);
                *it = k;
            }
        }
        return v.size() - 1;
    }
};

2731. 移动机器人 - 力扣(LeetCode)

暴力模拟如下 :

cpp 复制代码
class Solution {
public:
    const int mod = 1e9 + 7;
    int sumDistance(vector<int>& nums, string s, int d) 
    {
        using i64 = long long;
        int n = nums.size();
        while(d--)
        {
            for(int i = 0;i < n;i++)
            {
                nums[i] += (s[i] == 'R' ? 1 : -1);
                if(i && nums[i] == nums[i - 1])
                swap(s[i], s[i - 1]);
            }
        }
        i64 ans = 0;
        for(int i = 0; i < n; i++)
        {
            for(int j = i + 1;j < n;j++)
            ans = (ans % mod + (abs(v[i] - v[j]) % mod)) % mod;
        }
        return ans; 
    }
};

看数据范围d == 1e9

可见该题解在处理d秒时的时间复杂度应当不超过O(n)

因此:上解需要优化

当我们碰撞的时候:

cpp 复制代码
                if(i && nums[i] == nums[i - 1])
                swap(s[i], s[i - 1]);

交换俩者的方向,那也等于交换俩个机器人的效果,于是我们可以忽略碰撞影响,直接求d秒无碰撞的相对位置即可。

举一个简单的例子:

A = 0 == >> R

B = 2 == >> L

d = 10;

在1秒的时候交换方向

A = 1 == >> L

B = 1 == >> R

10s后:

A = -8 == >> L

B = 10 == >> R;

直接求相对距离

A = 10 == >> R

B = -8 == >> L

因此直接求d秒无碰撞的相对位置对最终答案无影响

此时: 由数据范围nums最大可为2e9,d 最大为1e9 >> 2147483647

爆int,需要i64数据类型进行存储

可得:

cpp 复制代码
class Solution {
public:
    const int mod = 1e9 + 7;
    int sumDistance(vector<int>& nums, string s, int d) 
    {
        using i64 = long long;
        int n = nums.size();
        vector<i64> v(n);
        for(int i = 0;i < n; i++)
        v[i] = nums[i] + (s[i] == 'R' ? d : -d);
        i64 ans = 0;
        for(int i = 0; i < n; i++)
        {
            for(int j = i + 1;j < n;j++)
            ans = (ans % mod + (abs(v[i] - v[j]) % mod)) % mod;
        }
        return ans; 
    }
};

再看数据范围

n的范围为2,1e5

仅看ans求值的第一轮循环1e5 * (1e5 - 1)显然超时

对于ans的求值过程有这么一种情况

对于任意 i 0,n前有i个数,后有n - i个数 == >> i * (n - i)个数对都会进行一次加(vi - vi- 1)的值

可得:

cpp 复制代码
class Solution {
public:
    const int mod = 1e9 + 7;
    int sumDistance(vector<int>& nums, string s, int d) 
    {
        using i64 = long long;
        int n = nums.size();
        vector<i64> v(n);
        for(int i = 0;i < n; i++)
        v[i] = nums[i] + (s[i] == 'R' ? d : -d);
        sort(v.begin(),v.end());
        i64 ans = 0;
        for (int i = 1; i < n; i++) 
        {
            ans = ((v[i] - v[i - 1]) * i % mod * (n - i) + ans) % mod;
        }
        return ans; 
    }
};

121. 买卖股票的最佳时机 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int ans = 0;
        int pre = prices[0];
        for(auto & x : prices)
        {
            pre = min(pre,x);
            ans = max(ans, x - pre);
        }
        return ans;
    }
};

64. 最小路径和 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) 
    {
        int m = grid.size();
        int n = grid[0].size();
        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(0 == i && 0 == j)continue;
                if(0 == i) grid[i][j] += grid[i][j - 1];
                else if(0 == j)grid[i][j] += grid[i - 1][j];
                else grid[i][j] += min(grid[i][j - 1],grid[i - 1][j]);
            }
        }         
        return grid[m - 1][n - 1];
    }
};

62. 不同路径 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    int uniquePaths(int m, int n) {
        using i64 = int64_t;
        i64 ans = 1;
        int x = n, y = 1;
        while(y < m)
        {
            ans = ans * x / y;
            x++;y++;
        }
        return ans;
    }
};

63. 不同路径 II - 力扣(LeetCode)

不额外开数组的方法

cpp 复制代码
class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) 
    {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n;j++)
            {
                obstacleGrid[i][j] ^= 1;
                if(!i && !j)continue;
                else if(!i) 
                {
                    if(obstacleGrid[i][j] == 0)continue;
                    obstacleGrid[i][j] += obstacleGrid[i][j - 1] - 1;
                }
                else if(!j)
                {
                    if(obstacleGrid[i][j] == 0)continue;
                    obstacleGrid[i][j] += obstacleGrid[i - 1][j] - 1;
                }
                else 
                {
                    if(obstacleGrid[i][j] == 0)continue;
                    obstacleGrid[i][j] += (obstacleGrid[i][j - 1] + obstacleGrid[i - 1][j]) - 1;
                }
            }
        }
        return obstacleGrid[m - 1][n - 1];
    }
};

或者额外开一个数组

cpp 复制代码
class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) 
    {
        int n = obstacleGrid.size(), m = obstacleGrid.at(0).size();
        vector <int> dp(m, 0);
        dp[0] = 1 - obstacleGrid[0][0];
        for (int i = 0; i < n; i++) 
        {
            for (int j = 0; j < m; j++) 
            {
                if(obstacleGrid[i][j] == 1)
                dp[j] = 0;
                else if(j && obstacleGrid[i][j - 1] == 0)//无需判断j == 0
                dp[j] += dp[j - 1];   
            }
        }
        return dp.back();
    }
};

2136. 全部开花的最早一天 - 力扣(LeetCode)

简单的贪心然后结构体排序(也可以创建数组记录位置访问)

cpp 复制代码
class Solution {
public:
    struct node
    {
        int id, p, g;
        node(int a,int b, int c) : id(a), p(b), g(c){};
    };
    int earliestFullBloom(vector<int>& plantTime, vector<int>& growTime) 
    {
        vector<node>v;
        int n = plantTime.size();
        for(int i = 0; i < n; i++)
        v.emplace_back(i,plantTime[i],growTime[i]);
        sort(v.begin(),v.end(),[&](auto x,auto y) {return x.g > y.g;});
        int ans = 0, pre = 0;
        for(auto x : v)
        {
            ans = max(ans, pre + x.p + x.g);
            pre += x.p;
        }
        return ans;
    }
};

605. 种花问题 - 力扣(LeetCode)

动态规划

cpp 复制代码
class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) 
    {
        int m = flowerbed.size();
        if(1 == m)return !flowerbed[0] >= n;
        else if(2 == m)return ((!flowerbed[0] && !flowerbed[1]) >= n);
        int dp[m][2];//第i个位置种|不种最大的收获数
        memset(dp, 0, sizeof dp);
        if(!flowerbed[0] && !flowerbed[1])
        {
            dp[0][1] = 1;
            dp[1][0] = 1;
            dp[1][1] = 1 - flowerbed[2];
        }
        for(int i = 2; i < m - 1; i++)
        {
            if(!flowerbed[i] && !flowerbed[i + 1] && !flowerbed[i - 1])
            {
                dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + 1);
                dp[i][0] = dp[i - 1][1];
            }
            else
            {
                dp[i][1] = max(dp[i - 1][1], dp[i - 1][0]);
                dp[i][0] = max(dp[i - 1][1], dp[i - 2][1]);
            }
        }
        if(!flowerbed[m - 1] && !flowerbed[m - 2])
        {
            dp[m - 1][1] = max(dp[m - 2][0] + 1,dp[m - 2][0]);
            dp[m - 1][0] = max(dp[m - 1][1], dp[m - 2][1]);
        }
        else
        dp[m - 1][0] = max(dp[m - 2][1],dp[m - 2][0]);
        return max(dp[m - 1][0], dp[m - 1][1]) >= n;
    }
};

贪心

cpp 复制代码
class Solution {
public:
    bool canPlaceFlowers(vector<int> &flowerbed, int n) 
    {
        int m = flowerbed.size();
        flowerbed.insert(flowerbed.begin(),0);
        flowerbed.emplace_back(0);
        for(int i = 1; i <= m; i++)
        {
            if(!flowerbed[i] && !flowerbed[i - 1] && !flowerbed[i + 1])
            {
                flowerbed[i] = 1;
                n--;
            }
        }
        return n <= 0;
    }
};

740. 删除并获得点数 - 力扣(LeetCode)

简单分析一下:

每一个数字其实只有2个状态选 or 不

可得预处理每一个数初始状态(不选为0,选为所有x的个数 * x)累加即可

cpp 复制代码
for(auto &x : nums)
   dp[x][1] += x;
       

每选一个树 i 删去 i + 1 和 i - 1

故我们可以将 i - 1视为 i 的父节点, i + 1视为 i 的子节点(此时思路就向树形dp经典题"参加舞会"一样如果i节点参与,其子节点和父节点不参与)

可得

cpp 复制代码
 for(int i = 2; i <= n;i++)
        {
            dp[i][1] += dp[i - 1][0];
            dp[i][0] += dp[i - 1][1];
        }

再考虑特殊情况:中间断层 1 5 or 任意不连续数字串

此时对与5 显然 其没有父节点 和 子节点(无法正常转移)

那么倒退4,我们构建4节点,因为其本身不存在选和不选都不影响最终结果

可得

cpp 复制代码
            if(!dp[i][1])
            {
                dp[i][1] = dp[i][0] = mx;
                continue;
            }

由于每一个节点的权值大小不同,对于第i个节点为true的时候有特殊情况(即选的权值不如不选的情况)

可得

cpp 复制代码
                dp[i][1] = max(dp[i][1] + dp[i - 1][0], dp[i - 1][1]);
                dp[i][0] += dp[i - 1][1];

由于题目数据范围为

故进行转移时只用转移1e4次即可

cpp 复制代码
//using i64 = int64_t;
class Solution {
public:
    const int maxn = 1e4 + 10;
    int dp[10010][2];
    int deleteAndEarn(vector<int>& nums) 
    {
        //视为树形dp(easy版)
        //例如:样例一 == >> 2 3 4
        //样例二 == >> 4 9 4    
        memset(dp, 0, sizeof dp);
        for(auto &x : nums)
        dp[x][1] += x;
        int mx = 0;
        for(int i = 1; i <= 10000; i++)
        {
            if(!dp[i][1])
            {
                dp[i][1] = dp[i][0] = mx;
                continue;
            }
            else
            {
                dp[i][1] = max(dp[i][1] + dp[i - 1][0], dp[i - 1][1]);
                dp[i][0] += dp[i - 1][1];
            }
            mx = max({mx,dp[i][1],dp[i][0]});
        }
        return max(dp[10000][1], dp[10000][0]);
    }
};

时间复杂度:常数级

1333. 餐厅过滤器 - 力扣(LeetCode)

简单的按规则排序,去除几个不满足的条件然后排序返回即可

cpp 复制代码
#include<algorithm>
class Solution {
public:
    vector<int> filterRestaurants(vector<vector<int>>& restaurants, int veganFriendly, int maxPrice, int maxDistance) 
    {
        vector<int>ans;
        std::sort(restaurants.begin(),restaurants.end(),[](vector<int>& a,vector<int>& b)
        {
            return a[1] == b[1] ? a[0] > b[0] : a[1] > b[1]; 
        	return true;
        });
        if(veganFriendly)
        for(auto x : restaurants)
        {
            if(!x[2] || x[3] > maxPrice || x[4] > maxDistance)continue;
            ans.emplace_back(x[0]);
        }
        else
        for(auto x : restaurants)
        {
            if( x[3] > maxPrice || x[4] > maxDistance)continue;
            ans.emplace_back(x[0]);
        }
        return ans;
    }
};

1137. 第 N 个泰波那契数 - 力扣(LeetCode)

一题简单的递推,也是没什么好说的

cpp 复制代码
class Solution {
public:
    int tribonacci(int n) {
        std::array<int,3> ans = {0, 1, 1};
        if(n <= 2)
        return ans[n];
        // 0 1 1 2 4 7
        for(int i = 0; i <= n - 3; i++)
        {
            int d = 0;
            for(int j = 0; j < 3; j++)
            {
               // std::cout << ans[j] << " ";
                d += ans[j];
                if(2 - j)ans[j] = ans[j + 1];
            }
          //  std::cout << "\n" << d << " " << "\n";
            ans[2] = d;
        }
        return ans[2];
    }
};

790. 多米诺和托米诺平铺 - 力扣(LeetCode)

方法一:状态压缩dp

cpp 复制代码
class Solution {
public:
    int mod = 1e9 + 7;
    int numTilings(int n) 
    {
        using i64 = int64_t;
        //按列表达状态 00 10 01 11
        i64 dp[n + 1][12];//平铺到第i 列时状态为 ...... 的方案数
        memset(dp, 0, sizeof dp);
        dp[0][1 << 1 | 1] = 1;
        for(int i = 1; i <= n;i++)
        {
            dp[i][0] = dp[i - 1][1 << 1 | 1];
            dp[i][1 << 1] = (dp[i - 1][0] + dp[i - 1][1]) % mod;
            dp[i][1] = (dp[i - 1][0] + dp[i - 1][1 << 1]) % mod;
            dp[i][1 << 1 | 1] = (dp[i - 1][0] + dp[i - 1][1] + dp[i - 1][1 << 1 | 1] + dp[i - 1][1 << 1]) % mod;
        }
        return dp[n][1 << 1 | 1] % mod;
    }
};

主要是方法二:学习别人的想法和写法

作者:灵茶山艾府

链接:https://leetcode.cn/problems/domino-and-tromino-tiling/submissions/

来源:力扣(LeetCode)

cpp 复制代码
class Solution {
    const int MOD = 1e9 + 7;
public:
    int numTilings(int n) {
        if (n == 1) return 1;
        long f[n + 1];
        f[0] = f[1] = 1;
        f[2] = 2;
        for (int i = 3; i <= n; ++i)
            f[i] = (f[i - 1] * 2 + f[i - 3]) % MOD;
        return f[n];
    }
};

1653. 使字符串平衡的最少删除次数 - 力扣(LeetCode)

cpp 复制代码
// 动态规划解一
class Solution 
{
public:
    int minimumDeletions(string s) 
    {
        int n = s.size();
        int* dp = new int[s.size()+1];
        fill(dp, dp + n + 1, 0);
        int numb = 0;
        if(s[0]=='b')numb++;
        for (int i = 1; i < n; i++)
        {
            //删除情况:要么是把a之前的b全部删除,要么删掉这个a本身
            if (s[i] == 'a')
            {
                //如果是a,选择删掉之前b或者删掉自己
                dp[i] = min(dp[i - 1] + 1, numb);
            }

            else
            {
                //如果为b状态和前者一样,记录其存在数
                numb++;
                dp[i] = dp[i - 1];
            }
        }
        return dp[n-1];
    }
};

//动态规划解二

class Solution {
public:
    int minimumDeletions(string s) {
        int numb = 0, ans = 0;
        for (auto i : s) {
            if ('a' == i)
            {
                ans = min(ans + 1, numb);
            }
            else
            {
                numb++;
            }
        }
        return ans;
    }
};


//栈区解
class Solution {
public:
    int minimumDeletions(string s)
    {
        stack<char>st;
        int ans = 0;
        for (auto i : s)
         {
            if ('b' == i)
            {
                st.push(i);
            }
            else if (!st.empty())
            {
                st.pop();
                ans++;
            }
        }
        return ans;
    }
};

class Solution {
public:
    int minimumDeletions(string s) {
        // 前缀和解法
        int n = s.length();
        vector<int> sumA(n + 1);
        vector<int> sumB(n + 1);
        for (int i = 0; i < n; ++i) 
        {
            sumA[i + 1] = sumA[i] + (s[i] == 'a');
            sumB[i + 1] = sumB[i] + (s[i] == 'b');
        }
        int ans =  sumA[n];//得到所有的a值
        for (int i = 1; i <= n; ++i) {
            //逐步比较删a,还是删b
            ans = min(ans, sumB[i] + sumA[n] - sumA[i]);
        }
        return ans;
    }
};
//2022 0306
相关推荐
神明不懂浪漫8 小时前
【第五章】Java中的继承与多态
java·开发语言
AI多Agent协作实战派10 小时前
AI多Agent协作系统实战(十七):凌晨4点,我的AI系统在“假装工作“——3个bug同时爆炸的5小时
java·前端·bug
gaolei_eit10 小时前
Java+Ai+vue
java·spring·maven
qq_25183645710 小时前
基于java Web 动漫视频网站毕业论文
java·开发语言·前端
LayZhangStrive10 小时前
JUC相关的函数、注解、变量杂记
java·面试·多线程·juc
未秃头的程序猿10 小时前
给公司做了个AI客服Agent,用的Spring AI 1.0,3天上线领导拍板了
java·后端·ai编程
来一碗刘肉面10 小时前
栈的应用(表达式求值)
数据结构·算法
曹牧10 小时前
Eclipse 批量文本替换
java·ide·eclipse
程序员清风10 小时前
OpenAI官方发布最新提示词技巧!
java·后端·面试
一只枫林10 小时前
MySQL内、外连接知识点汇总
java·前端·数据库