leetcode-2311.小于等于k的最长二进制子序列
题目描述
解题思路
这一题要求是子序列,如果改成连续子序列那难度就不是一个量级了。子序列是什么呢?子序列就是这个字符串中取出若干个字符,按原先出现的顺序组合形成的字符串。比如说00101010这个字符串,00000是它的一个子序列,101010是它的一个连续子序列。
那么首先如果,一个很简单的想法是,把所有0全部拿出来组成一个子序列,它的值一定是小于等于k的,因为此时值是0。然后看看哪些1能插入。
那么由于字符串越靠前的1插入带来的值增长越大,所以从字符串尾部往前遍历,选择能插入的1插入。当插入一个1时,带来的值增长与它当前位置距离末尾字符位置的距离pow_有关,为pow(2,pow_)。那么我们可以用1<<pow_来计算。
这一题潜在的坑点在于,字符串s可能很长,那么这个长度我一直计算左移会带来数值溢出的问题。
题目给的k有范围,在int类型中,所以31位以内的值比较是安全的(int 有1位表示正负)。若pow_超过31位,就无需计算左移,直接跳过1即可,因为这样带来的值增长一定比k大。
代码
int longestSubsequence(string s, int k) {int pow_ = -1, sum = 0,ret = 0;for(int i = s.size() - 1;i >= 0; i--){
pow_ ++;if(s[i] == '1'){if(pow_ >= 31) continue;else if(int tmp = sum + (1 << pow_);tmp > k) continue;else
sum = tmp;}
ret ++;} return ret;
}