Leetcode.2311 小于等于 K 的最长二进制子序列

题目链接

Leetcode.2311 小于等于 K 的最长二进制子序列 rating : 1840

题目描述

给你一个二进制字符串 s 和一个正整数 k k k

请你返回 s最长 子序列,且该子序列对应的 二进制 数字小于等于 k

注意:

  • 子序列可以有 前导 0
  • 空字符串视为 0 0 0
  • 子序列 是指从一个字符串中删除零个或者多个字符后,不改变顺序得到的剩余字符序列。

示例 1:

输入:s = “1001010”, k = 5
输出:5
解释:s 中小于等于 5 的最长子序列是 “00010” ,对应的十进制数字是 2 。
注意 “00100” 和 “00101” 也是可行的最长子序列,十进制分别对应 4 和 5 。
最长子序列的长度为 5 ,所以返回 5 。

示例 2:

输入:s = “00101001”, k = 1
输出:6
解释:“000001” 是 s 中小于等于 1 的最长子序列,对应的十进制数字是 1 。
最长子序列的长度为 6 ,所以返回 6 。

提示:

  • 1 ≤ s . l e n g t h ≤ 1000 1 \leq s.length \leq 1000 1s.length1000
  • s [ i ] s[i] s[i] 要么是 '0' ,要么是 '1'
  • 1 ≤ k ≤ 1 0 9 1 \leq k \leq 10^9 1k109

解法:贪心

首先我们先统计 0 的数量,然后从低位到高位一次插入 1 ,最后一个小于等于 k k k 的子串就是我们的答案,最后返回长度即可。

比如示例一: s = "1001010" ,k = 5。

首先先统计所有的 0,即 ss = "0000"

  • 插入第一个 1,ss = "00010",此时值为 2 2 2 , 2 < k 2 < k 2<k
  • 插入第二个 1,ss = "001010",此时值为 10 10 10 10 < k 10 < k 10<k

所以 ss = "00010",就是答案,我们最终返回它的长度即可。

时间复杂度: O ( n ) O(n) O(n)

C++代码:

class Solution {
public:
    int longestSubsequence(string s, int k) {
        int ans = 0 , n = s.size();

        for(auto c:s){
            if(c == '0') ans++;
        }

        long long t = 0,j = 1;
        
        for(int i = n - 1;i >= 0;i--,j <<= 1){
            if(s[i] == '1') t += j;
            if(t > k) break;
            if(j > 2e9) break;
            if(s[i] == '1') ans++;
        }

        return ans;
    }
};

你可能感兴趣的:(Leetcode,贪心,位运算)