comments | difficulty | edit_url | rating | source | tags | ||||
---|---|---|---|---|---|---|---|---|---|
true |
Medium |
1912 |
Weekly Contest 245 Q2 |
|
You are given two strings s
and p
where p
is a subsequence of s
. You are also given a distinct 0-indexed integer array removable
containing a subset of indices of s
(s
is also 0-indexed).
You want to choose an integer k
(0 <= k <= removable.length
) such that, after removing k
characters from s
using the first k
indices in removable
, p
is still a subsequence of s
. More formally, you will mark the character at s[removable[i]]
for each 0 <= i < k
, then remove all marked characters and check if p
is still a subsequence.
Return the maximum k
you can choose such that p
is still a subsequence of s
after the removals.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
Example 1:
Input: s = "abcacb", p = "ab", removable = [3,1,0] Output: 2 Explanation: After removing the characters at indices 3 and 1, "abcacb" becomes "accb". "ab" is a subsequence of "accb". If we remove the characters at indices 3, 1, and 0, "abcacb" becomes "ccb", and "ab" is no longer a subsequence. Hence, the maximum k is 2.
Example 2:
Input: s = "abcbddddd", p = "abcd", removable = [3,2,1,4,5,6] Output: 1 Explanation: After removing the character at index 3, "abcbddddd" becomes "abcddddd". "abcd" is a subsequence of "abcddddd".
Example 3:
Input: s = "abcab", p = "abc", removable = [0,1,2,3,4] Output: 0 Explanation: If you remove the first index in the array removable, "abc" is no longer a subsequence.
Constraints:
1 <= p.length <= s.length <= 105
0 <= removable.length < s.length
0 <= removable[i] < s.length
p
is a subsequence ofs
.s
andp
both consist of lowercase English letters.- The elements in
removable
are distinct.
We notice that if removing the characters at the first
We define the left boundary of the binary search as
After the binary search ends, we return the left boundary
The time complexity is
class Solution:
def maximumRemovals(self, s: str, p: str, removable: List[int]) -> int:
def check(k: int) -> bool:
rem = [False] * len(s)
for i in removable[:k]:
rem[i] = True
i = j = 0
while i < len(s) and j < len(p):
if not rem[i] and p[j] == s[i]:
j += 1
i += 1
return j == len(p)
l, r = 0, len(removable)
while l < r:
mid = (l + r + 1) >> 1
if check(mid):
l = mid
else:
r = mid - 1
return l
class Solution {
private char[] s;
private char[] p;
private int[] removable;
public int maximumRemovals(String s, String p, int[] removable) {
int l = 0, r = removable.length;
this.s = s.toCharArray();
this.p = p.toCharArray();
this.removable = removable;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (check(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
}
private boolean check(int k) {
boolean[] rem = new boolean[s.length];
for (int i = 0; i < k; ++i) {
rem[removable[i]] = true;
}
int i = 0, j = 0;
while (i < s.length && j < p.length) {
if (!rem[i] && p[j] == s[i]) {
++j;
}
++i;
}
return j == p.length;
}
}
class Solution {
public:
int maximumRemovals(string s, string p, vector<int>& removable) {
int m = s.size(), n = p.size();
int l = 0, r = removable.size();
bool rem[m];
auto check = [&](int k) {
memset(rem, false, sizeof(rem));
for (int i = 0; i < k; i++) {
rem[removable[i]] = true;
}
int i = 0, j = 0;
while (i < m && j < n) {
if (!rem[i] && s[i] == p[j]) {
++j;
}
++i;
}
return j == n;
};
while (l < r) {
int mid = (l + r + 1) >> 1;
if (check(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
}
};
func maximumRemovals(s string, p string, removable []int) int {
m, n := len(s), len(p)
l, r := 0, len(removable)
check := func(k int) bool {
rem := make([]bool, m)
for i := 0; i < k; i++ {
rem[removable[i]] = true
}
i, j := 0, 0
for i < m && j < n {
if !rem[i] && s[i] == p[j] {
j++
}
i++
}
return j == n
}
for l < r {
mid := (l + r + 1) >> 1
if check(mid) {
l = mid
} else {
r = mid - 1
}
}
return l
}
function maximumRemovals(s: string, p: string, removable: number[]): number {
const [m, n] = [s.length, p.length];
let [l, r] = [0, removable.length];
const rem: boolean[] = Array(m);
const check = (k: number): boolean => {
rem.fill(false);
for (let i = 0; i < k; i++) {
rem[removable[i]] = true;
}
let i = 0,
j = 0;
while (i < m && j < n) {
if (!rem[i] && s[i] === p[j]) {
j++;
}
i++;
}
return j === n;
};
while (l < r) {
const mid = (l + r + 1) >> 1;
if (check(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
}
impl Solution {
pub fn maximum_removals(s: String, p: String, removable: Vec<i32>) -> i32 {
let m = s.len();
let n = p.len();
let s: Vec<char> = s.chars().collect();
let p: Vec<char> = p.chars().collect();
let mut l = 0;
let mut r = removable.len();
let check = |k: usize| -> bool {
let mut rem = vec![false; m];
for i in 0..k {
rem[removable[i] as usize] = true;
}
let mut i = 0;
let mut j = 0;
while i < m && j < n {
if !rem[i] && s[i] == p[j] {
j += 1;
}
i += 1;
}
j == n
};
while l < r {
let mid = (l + r + 1) / 2;
if check(mid) {
l = mid;
} else {
r = mid - 1;
}
}
l as i32
}
}
/**
* @param {string} s
* @param {string} p
* @param {number[]} removable
* @return {number}
*/
var maximumRemovals = function (s, p, removable) {
const [m, n] = [s.length, p.length];
let [l, r] = [0, removable.length];
const rem = Array(m);
const check = k => {
rem.fill(false);
for (let i = 0; i < k; i++) {
rem[removable[i]] = true;
}
let i = 0,
j = 0;
while (i < m && j < n) {
if (!rem[i] && s[i] === p[j]) {
j++;
}
i++;
}
return j === n;
};
while (l < r) {
const mid = (l + r + 1) >> 1;
if (check(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
};
class Solution {
fun maximumRemovals(s: String, p: String, removable: IntArray): Int {
val m = s.length
val n = p.length
var l = 0
var r = removable.size
fun check(k: Int): Boolean {
val rem = BooleanArray(m)
for (i in 0 until k) {
rem[removable[i]] = true
}
var i = 0
var j = 0
while (i < m && j < n) {
if (!rem[i] && s[i] == p[j]) {
j++
}
i++
}
return j == n
}
while (l < r) {
val mid = (l + r + 1) / 2
if (check(mid)) {
l = mid
} else {
r = mid - 1
}
}
return l
}
}