算法:回文检测的学习引申

背景 

回文检测是我在学习JavaScript的数组内容时接触到的一个比较典型的项目。 
首先,我们来看看回文的定义: 若一个字符串等于将它反转后的结果,那可以称这个字符串是一个回文,常见的有: 
● “ABA” 
● “121” 
● “上海自来水来自海上”等等等等 
接下来通过3道题目来实现不同程度的回文检测。 

题一 

创建一个回文检测页面,支持用户输入文本后点击“Check”按钮可以判断输入的文本是不是回文,并输出判断结果。 
解题思路: 
1. 创建基础HTML(body节点需要包含至少输入框、检查按钮、结果输出框); 
2. 通过JS获取用户输入的值getValue 
3. 将获取的值转化为数组 .split() 
4. 将数组进行反转后得到新的数组 .reverse() 
5. 将新数组转化为新的字符串 .join() 
6. 判断新旧字符串是否相等,相等即为回文 
7. 输出判断结果 
示例代码: 
//初始化变量 
const userInput = document.getElementById("text-input"); 
const checkBtn = document.getElementById("check-btn"); 
const result = document.getElementById("result"); 
 //设置判断逻辑 
function isPalindrome(str){ const strReverse = str.toLowerCase().split('').reverse().join(''); return str.toLowerCase() == strReverse ? true : false; } 
 //设置输出规则 
const outputResult = (str) => { if(str == ""){ alert("请先输入文本"); }else if(isPalindrome(str)){ result.innerText = `${str} 是一个回文。` }else{ result.innerText = `${str} 不是回文。` } } 
 //为Check按钮设置点击事件侦听 
checkBtn.addEventListener('click', () =>outputResult(userInput.value)); 

题二 

在题一的基础上,对用户输入的值进行空格的过滤后再进行判断。 
解题思路: 
1. 在判断逻辑中使用.replace()方法将str中的空格替换为空串“”。 
示例代码: 
//初始化变量 
const userInput = document.getElementById("text-input"); 
const checkBtn = document.getElementById("check-btn"); 
const result = document.getElementById("result"); 
//设置判断逻辑 
function isPalindrome(str){ const strReverse = str.replace(/[\s]/g, "").toLowerCase().split('').reverse().join(''); return str.replace(/[\s]/g, "").toLowerCase() == strReverse ? true : false; } 
 //设置输出规则 
const outputResult = (str) => { if(str == ""){ alert("请先输入文本"); }else if(isPalindrome(str)){ result.innerText = `${str} 是一个回文。` }else{ result.innerText = `${str} 不是回文。` } } 
 //为Check按钮设置点击事件侦听 
checkBtn.addEventListener('click', () =>outputResult(userInput.value)); 

题三 

除了要检测字符串是不是一个回文外,还需要检测它有多少个回文子串。 
子串:从字符串中任意截取的部分均是字符串的子串,若子串满足回文定义,则认为该子串是回文子串。 
解题思路: 
1. 暴力穷举法 
2. 构造获取给定str中的所有子串的函数 a. 将str转化为数组 .split()方法 b. 捕获所有的子串.slice()方法 c. 将捕获的子串推入新数组 .push()方法 
3. 循环为新数组的元素转化为字符串后调用判断逻辑 
4. 输出字符串本身是否回文串,以及其回文子串的个数 
示例代码: 
//初始化变量 
const userInput = document.getElementById("text-input"); 
const checkBtn = document.getElementById("check-btn"); 
const result = document.getElementById("result"); 
 //设置判断逻辑 function isPalindrome(str){ const strReverse = str.replace(/[\s]/g, "").toLowerCase().split('').reverse().join(''); return str.replace(/[\s]/g, "").toLowerCase() == strReverse ? true : false; } 
 //获取回文子串个数 const countPalindromeSubstrings = (str) =>{ //设置捕获条件变量 const arr = str.split(""); const n = arr.length; const Substrs = []; //设置捕获逻辑 for(let start = 0; start < n; start++){ for(let indexEnd = start; indexEnd < n; indexEnd++){ const Substr = arr.slice(start, indexEnd + 1).join(); Substrs.push(Substr); } } //判断回文子串个数方法 let count = 0 ; for(let i = 0; i < Substrs.length; i++){ if(isPalindrome(Substrs[i])){ count++; } } return count; } 
//设置输出规则 
const outputResult = (str) => { if(str == ""){ alert("请先输入文本"); }else if(isPalindrome(str)){ result.innerText = `${str} 是一个回文。其回文子串有${countPalindromeSubstrings(str)}个。` }else{ result.innerText = `${str} 不是回文。其回文子串有${countPalindromeSubstrings(str)}个。` } } 
//为Check按钮设置点击事件侦听 
checkBtn.addEventListener('click', () =>outputResult(userInput.value)); 
 

拓展 

通过以上三道题,对字符串、数组的常见方法、基础的正则用法、以及基础的循环语句(for循环)、条件语句(if语句)均有了初步的认知。 在解决回文检测的过程中,我们还可以做更多的引申,包括: 1. 如果不用暴力穷举法,而基于回文本身的左右对称性质来计算回文子串的个数。 2. 如果修改子串的定义为不要求连续,任意组合都可以得到子串,又该如何计算。 3. 如果子串中的重复项要排除掉,又有哪几种方式处理呢。

评论