32场双周赛(模拟,模拟,前缀和加状态压缩)

 

1540. K 次操作转变字符串

class Solution {
    public boolean canConvertString(String s, String t, int k) {
        if(s.length() != t.length()) return false;
        int n = s.length();
        int[] arr = new int[26];
        int count = 0;
        for(int i = 0; i < n; i++) {
            if(s.charAt(i) != t.charAt(i)) {
                int num = (t.charAt(i) - s.charAt(i) + 26) % 26;
                arr[num]++;
                count++;
            }
        }
        for(int i = k; i >= 1; i--) {
            if(arr[i%26] != 0) {
                arr[i%26]--;
                if(--count == 0) return true;
            }
        }
        return count == 0;
    }
}

1541. 平衡括号字符串的最少插入次数

 

 

 

class Solution {
    public int minInsertions(String s) {
        int n = s.length();
        char[] arr = s.toCharArray();
        int left = 0, right = 0, res = 0;
        for(int i = n - 1; i >= 0; i--) {
            if(arr[i] == '(') {
                left++;
            } else {
                right++;
            }
            while(left > 0 && right >= 0) {
                if(right >= 2) {
                    right -= 2;
                    if(arr[i] == '(' && right % 2 != 0) {
                        right++;
                        res++;
                    }
                } else { 
                    res += 2 - right;
                    right = 0;
                }
                left -= 1;
            }
        }
        return res + ((right&1) == 0 ? right / 2 : (right + 1) / 2 + 1);
    }
}

1542. 找出最长的超赞子字符串

 

 分析:  

  首先,一个字符串可以重新排序得到一个回文字符串的充要条件是:对字符计数,出现奇数次的字符个数小于等于1。

  由此我们可以发现:我们没有必要知道这个数字到底出现了几次,我们只需要关心它到底是出现了奇数次还是偶数次。我们用 0,1 来表示出现了 偶数/奇数 次,由于需要统计的字符只有 0-9十个数字,因此我们只需要一个十位的二进制数 status  即可表示当前所有字符出现次数的奇偶状态,即第i位表示数字 ii 出现次数的奇偶性。  假设当前遇到的数字是 i ,那么更新它的状态就是 status ^= (1 << i) ,因为根据异或的特性,相同为0,不同为1,0异或任何数还是等于那个数,

  所以相当于我们只对第 ii 位进行了修改,改变对应二进制位的状态。

  我们遍历字符串维护这样一个 status,采用数组标记的思想,pre[status] 表示 status 出现的最早位置(对每一个出现过的状态进行标记)。

满足超赞字符串的条件:

再一次遇到之前已经出现过的 status,说明所有数字都出现了偶数次。(因为每一位二进制位的奇偶性都相同的话,不论都是1还是0,奇-奇=偶-偶=偶,都代表这些字符在中间这一段出现了偶数次,该超赞字符串的长度为 当前位置i - 最早出现的位置pre[status]当前位置i−最早出现的位置pre[status])

与之前出现过的 status 只有一个二进制位不同,说明这个不同的二进制位出现了奇数次 (奇-偶=偶-奇=奇),其余的二进制位出现了偶数次,仍然满足回文字符串的条件。针对这种情况,我们只需要从 0-9 枚举二进制位,然后看之前是否出现过即可,同时维护答案。

 

class Solution {
    public int longestAwesome(String s) {
        int n = s.length();
        int status = 0, res = 1;
        char[] arr = s.toCharArray();
        int[] pos = new int[1 << 10];
        Arrays.fill(pos,-2);
        pos[0] = -1;
        for(int i = 0; i < n; i++) {
            status ^= 1 << (arr[i] - '0');
            if(pos[status] != -2) {
                res = Math.max(res,i-pos[status]);
            } else {
                pos[status] = i;
            }
            for(int j = 0; j < 10; j++) {
                int state = status ^ (1 << j);
                if(pos[state] != -2) {
                    res = Math.max(res, i - pos[state]);
                }
            }
        }
        return res;
    }
}

 

 

 

posted @ 2020-08-10 19:29  Sexyomaru  阅读(120)  评论(0编辑  收藏  举报