代码编织梦想

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。

为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。

由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。

You are given two strings a and b of the same length. Choose an index and split both strings at the same index, splitting a into two strings: aprefix and asuffix where a = aprefix + asuffix, and splitting b into two strings: bprefix and bsuffix where b = bprefix + bsuffix. Check if aprefix + bsuffix or bprefix + asuffix forms a palindrome.

When you split a string s into sprefix and ssuffix, either ssuffix or sprefix is allowed to be empty. For example, if s = "abc", then "" + "abc""a" + "bc""ab" + "c" , and "abc" + "" are valid splits.

Return true if it is possible to form a palindrome string, otherwise return false.

Notice that x + y denotes the concatenation of strings x and y.

Example 1:

Input: a = "x", b = "y"
Output: true
Explaination: If either a or b are palindromes the answer is true since you can split in the following way:
aprefix = "", asuffix = "x"
bprefix = "", bsuffix = "y"
Then, aprefix + bsuffix = "" + "y" = "y", which is a palindrome.

Example 2:

Input: a = "xbdef", b = "xecab"
Output: false

Example 3:

Input: a = "ulacfd", b = "jizalu"
Output: true
Explaination: Split them at index 3:
aprefix = "ula", asuffix = "cfd"
bprefix = "jiz", bsuffix = "alu"
Then, aprefix + bsuffix = "ula" + "alu" = "ulaalu", which is a palindrome.

Constraints:

  • 1 <= a.length, b.length <= 105
  • a.length == b.length
  • a and b consist of lowercase English letters

题意:两个长度相同的字符串 a 和 b ,选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefix 和 asuffix ,满足 a = aprefix + asuffix ,同理,由 b 可以得到两个字符串 bprefix 和 bsuffix ,满足 b = bprefix + bsuffix 。判断 aprefix + bsuffix 或者 bprefix + asuffix 能否构成回文串,能则返回 true 。当你将一个字符串 s 分割成 sprefix 和 ssuffix 时, ssuffix 或者 sprefix 可以为空。


解法 贪心+双指针

600
注意,双指针前后缀贪心匹配结束后,两个指针指向的位置恰好就是「接下来要判断的回文串」的左右边界,所以这两块代码逻辑可以无缝对接。

class Solution {
public:
    bool checkPalindromeFormation(string a, string b) {
        function<bool(string, int, int)> isPalindrome = [&](const string &x, int l, int r) {
            while (l < r && x[l] == x[r]) ++l, --r;
            return l >= r;
        };
        // 双指针判断x的前缀和y的后缀是否组成回文
        function<bool(string, string)> check = [&](const string &x, const string &y) {
            for (int i = 0, j = y.size() - 1; i < j; ++i, --j) { // 相向双指针
                // x从前往后,与y从后往前对比,前后缀尽量匹配
                // ulac cfd , ula ccfd
                // zjiz alu , zji zalu
                if (x[i] != y[j]) { // 字符x[i]和y[j]不等,要组成回文
                    // 可能从i前分割开,于是要看y[i:j]是否回文
                    // 或者从j后分割开,于是要看x[i:j]是否回文
                    return isPalindrome(y, i, j) || isPalindrome(x, i, j);
                }
            }
            return true;
        };
        return check(a, b) || check(b, a); 
    }
}; 

解法2 中心扩展+双指针

还可使用中心扩展法LeetCode 647. Palindromic Substrings)。设 a p r e f i x a_{prefix} aprefix a a a m m m 个字符,因此在匹配的回文中也要取 b s u f f i x b_{suffix} bsuffix 的后 m m m 个字符。然后就要看剩下的 a a a b b b 正中心 n − 2 m n -2m n2m 个字符是否是回文串。

回文串分两种:

  • 奇数长度,中间的字母不用管,两侧的各自相等
  • 偶数长度,没有中间的字母,两侧的各自相等

x, y 字符串长度相同,令中心扩展检测回文串函数为 check(x, y, left) ,它从 x[left] 往左扩张、从 y[right] 往右扩展,然后彼此匹配。这里的 left 我们传进去 x.size() / 2 - 1 ,偶数时为左侧的中心、奇数时为中心左边那个位置right = x.size() - left - 1 为与中心对称的位置。

我们调用 check(a, a, left), check(b, b, left) 从中心向两侧分别检测字符串 a a a b b b ,不断扩展,直到字符不相同。然后看 a , b a, b a,b 哪个的中心回文串更长,具体是哪条更长不重要。

再以具有更长中心回文串的那个字符串为标准,将两个字符串前后缀分别拼接,并继续扩展检测,这次检测拼接后的字符串。即调用 check(a, b, left), check(b, a, left) ,这里的 left 是之前遍历结束的位置。

当再次结束检测时,如字符再次不相同,则匹配失败;如全部匹配成功,则 left 应该为-1。

结合下图观看,第一次检测时,字符串 a a a 的中心并没有回文串,而字符串 b b b 有一段合法回文串;第二次检测时, a p r e f i x + b s u f f i x a_{prefix} + b_{suffix} aprefix+bsuffix 通过测试。最终, a p r e f i x a_{prefix} aprefix b s u f f i x b_{suffix} bsuffix b b b 的中心子串组合起来,就是拼接后的回文串(所有有底色的字符):

// 中心扩展
class Solution {
public:
    bool checkPalindromeFormation(string a, string b) {
        int n = a.size();
        function<int(string, string, int)> check = [&](const string &x, const string& y, int left) {
            int right = n - left - 1;
            while (left >= 0 && right < n && x[left] == y[right]) --left, ++right;
            return left;
        };
        int left = n / 2 - 1; // 中心位置
        left = min(check(a, a, left), check(b, b, left));
        left = min(check(a, b, left), check(b, a, left));
        return left == -1;
    }
}

这种写法与第一种写法相反,是相反双指针

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/myRealization/article/details/129642730

leetcode 部分题解_umbrellasoft的博客-爱代码爱编程

算法思想 双指针排序 快速选择堆排序桶排序荷兰国旗问题 贪心思想二分查找分治搜索 BFSDFSBacktracking 动态规划 斐波那契数列矩阵路径数组区间分割整数最长递增子序列最长公共

leetcode刷题笔记(1)——基础题篇_cookie_sll的博客-爱代码爱编程

LeetCode刷题笔记(1)——基础题篇 还有不到一年的时间就要找工作了,现在开始刷LeetCode的编程题。 目标:每日1-2题,不仅要Accept,更要学会最优的解法。 针对做题学到的更优解法,记录如下,方便以后复

leetcode算法刷题指南_weixin_33806509的博客-爱代码爱编程

主要参考@CYC2018大佬的LeetCode题解 数组和矩阵 把数组中的 0 移到末尾 283. Move Zeroes (Easy) For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0

leetcode 从零单刷个人笔记整理(持续更新)_nju_chopinxbp的博客-爱代码爱编程

更新至2020.2.23 github:https://github.com/ChopinXBP/LeetCode-Babel 本人博客用于个人对知识点的记录和巩固。 用几乎所有可行的方法进行了实现和调优 下面每

leetcode题解-爱代码爱编程

算法思想 贪心思想 贪心思想保证每次操作都是局部最优的,并且最后得到的结果是全局最优的。 分配饼干 455. Assign Cookies (Easy) Input: [1,2], [1,2,3] Outp

LeetCode 目录-爱代码爱编程

LeetCode 目录 以表格的形式记录我写下的每一道题的博客位置, 以便查阅. 目前决定不以 LeetCode 的题目编号为顺序进行排列, 而是采用我的做题顺序. 编号题目标题题目难度题目类型解题思路时间复杂度备注00011. Two Sum*简单Array哈希表

leetcode 125、136、344、557、657、709、771、804、893、929-爱代码爱编程

文章目录 Algorithm 1125. 验证回文串1)problem2)answer3)solutionAlgorithm 2136. Single Number1)problem2)answer3)solution4)总结Algorithm 3344. Reverse String1)problem2)answer3)solutionAlgor

【leetcode】解题日记(未完待续)-爱代码爱编程

开坑,有生之年系列,希望有一天能解出 l e e t c

Leetcode题目练习总结(持续更新......)-爱代码爱编程

Leetcode题目练习 数组1.两数之和26. 删除排序数组中的重复项27. 移除元素35.搜索插入位置53.最大子序列66.加一88.合并两个有序数组118.杨辉三角119.杨辉三角2121.买卖股票的最佳时机122.买卖股票的最佳时机2167.两数之和2169.多数元素189.旋转数组217.存在重复元素219.存在重复元素2268.缺失数字

LeetCode记录总结-爱代码爱编程

LeetCode记录总结 本文章主要记录LeetCode刷题学到的知识 242.Valid Anagram 题目: Given two strings s and t , write a function to determine if t is an anagram of s. 我的解法: class Solution {

1616. 分割两个字符串得到回文串-爱代码爱编程

1616. 分割两个字符串得到回文串 给你两个字符串 a 和 b ,它们长度相同。请你选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefix 和 asuffix ,满足 a = aprefix + asuffix ,同理,由 b 可以得到两个字符串 bprefix 和 bsuffix ,满足 b = bprefi

AK F.*ing leetcode 流浪计划之回文串-爱代码爱编程

欢迎关注更多精彩 关注我,学习常用算法与数据结构,一题多解,降维打击。 文章目录 一、简介二、解题步骤三、作用四、经典算法介绍判断一个串是否为回文串(单次查询)普通情况判断指定字符多次子串查询动态规划法O(n^2)中心扩展法O(n^2)Manacher(马拉车算法) O(n)五、牛刀小试练习1 [最长回文子串](https://leetcode-

acwing leetcode 题目分类——配套基础课进阶课_啊枫_jiangchufeng的博客-爱代码爱编程

LeetCode 题目分类——配套基础课进阶课 1.基础 二分(满足一个条件的最值问题) LeetCode33 https://leetcode.com/problems/search-in-rotated-sorte

lc-1616. 分割两个字符串得到回文串(相向双指针、中心扩展)-爱代码爱编程

文章目录 [1616. 分割两个字符串得到回文串](https://leetcode.cn/problems/split-two-strings-to-make-palindrome/)暴力(超时)相向双指针优化法二