一天一大 lee(最短回文串)难度:困难-Day20200829
时间:2022-07-25
本文章向大家介绍一天一大 lee(最短回文串)难度:困难-Day20200829,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:[1]
给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例
- 示例 1
输入: "aacecaaa"
输出: "aaacecaaa"
- 示例 2
输入: "abcd"
输出: "dcbabcd"
抛砖引玉
思路
最直观想到的思路就是找到从 s 首位开始的最长回文字符串,再讲不是该串的部分颠倒拼接到 s 头部就得到了需要的结果
- s 从 0->s.length 枚举 s 的子串
- 判断枚举的子串是否为回文字符串
- 不是继续枚举
- 是返回 s 中不在该子串部分的颠倒字符+s
其中校验字符串是否为子串在:20200610:回文数 (难度:简单)中就用到过
/**
* @param {string} s
* @return {string}
*/
var shortestPalindrome = function (s) {
let len = s.length
// 从长到短求最长前缀回文字符
for (let i = len; i >= 0; i--) {
let _result = s.substring(0, i)
if (check(_result)) {
return Array.from(s.substring(i, len)).reverse().join('') + s
}
}
// 校验是否为回文字符串
function check(x) {
let str = '' + x
return Array.from(str).reverse().join('') === str
}
}
提交后会发现 119 / 120 个通过测试用例,存在 2 个测试用例没有通过
抛砖引玉
换种思路
在20200823: 重复的子字符串 (难度:简单)[2]中就用到了 KMP 算法去校验一个模式串是否匹配另外一个匹配串
- 将 s 和 s 字符颠倒 str 两个字符匹配,匹配上的部分则说明在 s 内部本事这两部是回文子串
- 在 KMP 算法中存在求最长公共前缀的逻辑(也是匹配时指针不连续跳转的序列),那么匹配时记录从哪个位置完成了匹配, 则该位置之前的部分都是需要,补充完成才能形成回文字符非部分
- 最后的问题,补充的字符从哪里来呢,从 s 中,但是如果补充的部分字符顺序和 s 中相同则不能形成回文片段,则需要截取 s 的片段颠倒后再拼接
KMP算法
- 实例 1:s->aacecaaa str->aaacecaa match -> 6 aaacecaa-aacecaa-0123456
- 实例 2:s->abcd str->dcba match -> 0 dcba---a---0
/**
* @param {string} s
* @return {string}
*/
var shortestPalindrome = function (s) {
let len = s.length,
str = s.split('').reverse().join('')
// 正反字符匹配求最长匹配位数
function kmp(query, pattern) {
let fail = Array(len).fill(-1)
// 最长公共前缀,不存在公共前缀填充-1
for (let i = 1; i < len; ++i) {
let j = fail[i - 1]
while (j != -1 && pattern[j + 1] != pattern[i]) {
j = fail[j]
}
if (pattern[j + 1] == pattern[i]) {
fail[i] = j + 1
}
}
// 校验 match记录匹配的位置
let match = -1
for (let i = 0; i < len; ++i) {
// 如果当前不匹配匹配,指针跳跃到前缀位置开始匹配
while (match != -1 && pattern[match + 1] != query[i]) {
match = fail[match]
}
// 如果当前位匹配,逐个向后匹配
if (pattern[match + 1] == query[i]) {
++match
}
}
return match
}
let num = kmp(str, s),
add = num == len - 1 ? '' : s.substring(num + 1)
return Array.from(add).reverse().join('') + s
}
参考资料
[1]
题目:: https://leetcode-cn.com/problems/shortest-palindrome/
[2]
20200823: 重复的子字符串 (难度:简单):https://krdxst.gitee.io/oneday_oneleetcode/leetcode/202008/20200823.html
- Android UI控件系列:LinearLayout(线性布局)
- 使用操作符重载,生成ORM实体类的SQL条件语句
- Dance In Heap(四):一些堆利用的方法(下)
- Mac系统的Proton恶意软件:卷!土!重!来!
- Erlang语言学习入门
- Android使用Ant进行apk多渠道打包
- Dance In Heap(三):一些堆利用的方法(中)
- Android性能优化篇:使用软引用和弱引用
- 使用泛型委托,构筑最快的通用属性访问器
- 记录容易忘记的方法
- 无需重新编译代码,在线修改表单
- 使用反射+缓存+委托,实现一个不同对象之间同名同类型属性值的快速拷贝
- 结构变量作为方法的参数调用,在方法内部使用的“坑”你遇到过吗?
- 使用表达式树,让访问者直接执行“角色”对象的方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- docker搭建环境如何配置端口
- Go语言入门(二)-流程控制
- 【Java8新特性】02 函数式接口和Lambda表达式实战练习:环绕执行模式使行为参数化
- Go语言入门(三)数组和切片
- 一天一大 leet(回文数)难度:简单 DAY-10
- 如何使用docker搭建PHP环境
- Go语言入门(四)Map&函数
- 一天一大 leet(每日温度)难度:中等 DAY-11
- Go语言入门(五)结构体&练习
- 利用hexo和github或coding 搭免费个人博客
- window 指令之 tree
- Go语言入门(六)结构体后续&指针
- 一天一大 leet(二叉树的序列化与反序列化)难度:困难 DAY-16
- 一天一大 leet(三数之和)难度:中等 DAY-12
- MongoDB Docker版本:基础入门和复制集