首页 > 其他分享 >【数据结构-前缀异或和】力扣1177. 构建回文串检测

【数据结构-前缀异或和】力扣1177. 构建回文串检测

时间:2024-08-25 18:24:25浏览次数:14  
标签:1177 子串 字符 子段 count 力扣 异或 queries 回文

给你一个字符串 s,请你对 s 的子串进行检测。

每次检测,待检子串都可以表示为 queries[i] = [left, right, k]。我们可以 重新排列 子串 s[left], …, s[right],并从中选择 最多 k 项替换成任何小写英文字母。

如果在上述检测过程中,子串可以变成回文形式的字符串,那么检测结果为 true,否则结果为 false。

返回答案数组 answer[],其中 answer[i] 是第 i 个待检子串 queries[i] 的检测结果。

注意:在替换时,子串中的每个字母都必须作为 独立的 项进行计数,也就是说,如果 s[left…right] = “aaa” 且 k = 2,我们只能替换其中的两个字母。(另外,任何检测都不会修改原始字符串 s,可以认为每次检测都是独立的)

示例:
输入:s = “abcda”, queries = [[3,3,0],[1,2,0],[0,3,1],[0,3,2],[0,4,1]]
输出:[true,false,false,true,true]
解释:
queries[0] : 子串 = “d”,回文。
queries[1] : 子串 = “bc”,不是回文。
queries[2] : 子串 = “abcd”,只替换 1 个字符是变不成回文串的。
queries[3] : 子串 = “abcd”,可以变成回文的 “abba”。 也可以变成 “baab”,先重新排序变成 “bacd”,然后把 “cd” 替换为 “ab”。
queries[4] : 子串 = “abcda”,可以变成回文的 “abcba”。

提示:
1 <= s.length, queries.length <= 10^5
0 <= queries[i][0] <= queries[i][1] < s.length
0 <= queries[i][2] <= s.length
s 中只有小写英文字母

class Solution {
public:
    vector<bool> canMakePaliQueries(string s, vector<vector<int>>& queries) {
        //异或 1 ^ 1 = 0, 1 ^ 0 = 1,说明偶数个会为0,奇数个会为1
        vector<int> count(s.size() + 1);
        for(int i = 0; i < s.size(); i++){
            count[i+1] = count[i] ^ (1 << (s[i] - 'a'));
        }

        vector<bool> res;
        for(auto &query : queries){
            int l = query[0], r = query[1], k = query[2];
            int x = count[r+1] ^ count[l];
            int bit = 0;
            while(x > 0){
                //x - 1说明二进制数最右边的1及右边全部变化,再取与,剔除x最右边1,然后最右边全为0.
                x &= x - 1;
                bit++;
            }
            res.push_back(bit <= k * 2 + 1);
        }
        return res;
    }
};

时间复杂度:O(n+m),其中 n 是字符串 s 的长度,m 是 queries 的长度。忽略统计位 1 的个数的时间复杂度。

空间复杂度:O(n),其中 n 是字符串 s 的长度。结果不计入空间复杂度。

这一题运用到的几个知识点:
1.按字符在字母表中的顺序记录到二进制数中
2.前缀异或和找出包含未能配对字符个数的子段
3.使用 x &= x - 1来计算出子段中1的个数

关于第一个知识点,<<是将一个二进制左移多少位,比如说 c 就是0001向左移两位,也就是0100。

第二个知识点也就是为什么int x = count[r+1] ^ count[l];可以找到这个子段包含字符奇偶数信息的二进制数。这是由于count[l]包含了从0到l-1的二进制,count[r]包含了0到l-1和l到r的二进制。

如果count[l]某个字符是奇数个(1),那么如果count[r]该字符是奇数个(1),说明子段为偶数个(0)
如果count[l]某个字符是奇数个(1),那么如果count[r]该字符是偶数个(0),说明子段是奇数个(1)
如果count[l]某个字符是偶数个(0),那么如果count[r]该字符是偶数个(0),说明子段是偶数个(0)
如果count[l]某个字符是偶数个(0),那么如果count[r]该字符是奇数个(1),说明子段是奇数个(1)

这也就说明子段的相关二进制可以通过前缀异或和的差来求。

第三个知识点也就是x &= x - 1输出1的个数,x - 1说明二进制数最右边的1及该1的右边全部取反。x与x-1取与,让x最右边1及其右边全部变为0。

标签:1177,子串,字符,子段,count,力扣,异或,queries,回文
From: https://blog.csdn.net/sjsjs11/article/details/141430181

相关文章

  • 力扣刷题(1)
    两数之和两数之和-力扣思路:动态开辟一个数组,用来存放下标;两个for循环嵌套来判断,数组中的两个数相加是否与target相等若相等,则将*returnSize赋值为2,表示数组中两个数,并将arr数组进行赋值若不存在两数相加为target的数,则将*returnSize赋值为0int*twoSum(int*nums,in......
  • 秋招力扣Hot100刷题总结——二叉树
    二叉树相关的题目基本上都会使用递归,因此做二叉树的题目时首先使用递归,明确递归结束的条件。1.二叉树的层序遍历题目链接题目要求:给你二叉树的根节点root,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。代码及思路使用队列存储每一层的节点,左边节点先......
  • 力扣热题100_贪心算法_55_跳跃游戏
    文章目录题目链接解题思路解题代码题目链接55.跳跃游戏给你一个非负整数数组nums,你最初位于数组的第一个下标。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回true;否则,返回false。示例1:输入:nums=[......
  • 力扣: 设计链表
    文章目录需求代码结尾需求你可以选择使用单链表或者双链表,设计并实现自己的链表。单链表中的节点应该具备两个属性:val和next。val是当前节点的值,next是指向下一个节点的指针/引用。如果是双向链表,则还需要属性prev以指示链表中的上一个节点。假设链表中的......
  • 力扣: 移除链表元素
    文章目录需求虚拟头结点法原头结点法结尾需求给你一个链表的头节点head和一个整数val,请你删除链表中所有满足Node.val==val的节点,并返回新的头节点。示例1:输入:head=[1,2,6,3,4,5,6],val=6输出:[1,2,3,4,5]示例2:输入:head=[],val=1输......
  • 76. 最小覆盖子串【 力扣(LeetCode) 】
    一、题目描述给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串,则返回空字符串“”。注意:对于t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量。如果s中存在这样的子串,我们保证......
  • 48. 旋转图像【 力扣(LeetCode) 】
    一、题目描述给定一个n×n的二维矩阵matrix表示一个图像。请你将图像顺时针旋转90度。你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。二、测试用例示例1:输入:matrix=[[1,2,3],[4,5,6],[7,8,9]]输出:[[7,4......
  • 力扣:有效的数独
    文章目录需求分析结尾需求请你判断一个9x9的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。数字1-9在每一行只能出现一次。数字1-9在每一列只能出现一次。数字1-9在每一个以粗实线分隔的3x3宫内只能出现一次。(请参考示例图)......
  • 力扣热题100_栈_739_每日温度
    文章目录题目链接解题思路解题代码题目链接739.每日温度给定一个整数数组temperatures,表示每天的温度,返回一个数组answer,其中answer[i]是指对于第i天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用0来代替。示例1:输入:tempe......
  • 力扣面试经典算法150题:跳跃游戏
    跳跃游戏今天的题目是力扣面试经典150题中的数组的中等难度题:跳跃游戏。题目链接:https://leetcode.cn/problems/jump-game/description/?envType=study-plan-v2&envId=top-interview-150题目描述给定一个非负整数数组nums,你最初位于数组的第一个下标,即nums[0]。数......