如何使用递归计算字符串中的所有回文?
How to count all the palindromes in a string using recursion?
我有一个检查字符串是否为回文的递归函数,但我的作业要求我计算字符串中回文的数量(例如 kayak 有 2 个)。
我真的很困惑如何实现一个计算回文数的递归函数。这是我当前的代码:
function isPalindrome(string) {
if (string.length <= 1) {
return true;
}
let [ firstLetter ] = string;
let lastLetter = string[string.length - 1];
if (firstLetter === lastLetter) {
let stringWithoutFirstAndLastLetters = string.substring(1, string.length - 1);
return isPalindrome(stringWithoutFirstAndLastLetters);
} else {
return false;
}
}
一种方法是首先 ,然后验证每个:
getAllSubstrings('kayak').filter(str => str.length >= 2 && isPalindrome(str))
function getAllSubstrings(str) {
var i, j, result = [];
for (i = 0; i < str.length; i++) {
for (j = i + 1; j < str.length + 1; j++) {
result.push(str.slice(i, j));
}
}
return result;
}
function isPalindrome(string) {
if (string.length <= 1) {
return true;
}
let [ firstLetter ] = string;
let lastLetter = string[string.length - 1];
if (firstLetter === lastLetter) {
let stringWithoutFirstAndLastLetters = string.substring(1, string.length - 1);
return isPalindrome(stringWithoutFirstAndLastLetters);
} else {
return false;
}
}
console.log(
getAllSubstrings('kayak').filter(str => str.length >= 2 && isPalindrome(str))
);
我认为接受的答案实际上不起作用。它不会计算回文,除非它们位于字符串的中心,并且只要它们以相同的字母开头和结尾,就会计算不是回文的子字符串。 CertainPerformance 的答案可能会起作用,但我认为这会导致检查很多不需要检查的字符串。这是我想出的,我认为它适用于我添加的额外测试。
function countPalindromes(string) {
if (string.length <= 1) {
return 0;
}
count = 0
for ( var i = 0; i < string.length; i++ ) {
count += countPalindromesCenteredAt(string, i)
count += countPalindromesCenteredAfter(string, i)
}
return count
}
function countPalindromesCenteredAt(string, i) {
count = 0
for ( var j = 1; i-j>=0 && i+j < string.length; j++ ) {
if (string.charAt(i-j) === string.charAt(i+j)) {
count += 1
}
else {
return count
}
}
return count
}
function countPalindromesCenteredAfter(string, i) {
count = 0
for ( var j = 1; i-j>=0 && i+j < string.length; j++ ) {
if (string.charAt(i-j+1) === string.charAt(i+j)) {
count += 1
}
else {
return count
}
}
return count
}
console.log(countPalindromes("kayak"));
console.log(countPalindromes("aya"));
console.log(countPalindromes("kayakcanoe"));
console.log(countPalindromes("kcanoek"));
当函数得到回文时很容易:
- 记录输入
- 没有边缘再试一次
- 输入不超过三个字符时停止
"kayak" -> "aya"
如果输入不是回文,请递归尝试“两端”,例如使用 "kayam"
尝试同时使用 "kaya"
和 "ayam"
并继续...
当字符串为 3 个(或更少)字符时,我们将停止递归。单个字符不是回文,检查两个或三个字符的字符串是否是回文是微不足道的。
kayam
|
+-------------+
| |
kaya ayam
| |
+-------+ +--------+
| | | |
kay aya aya yam
const reverse =
([...xs]) =>
xs.reverse().join("");
const is_palindrome =
a =>
a.length === 1 ? false
: a.length <= 3 ? a[0] === a[a.length-1]
: a === reverse(a);
const find_palindromes = str => {
const scan =
(x, xs = []) =>
x.length <= 3 ? xs.concat(is_palindrome(x) ? x : [])
: is_palindrome(x) ? xs.concat
( x
, scan(x.slice(1, -1))
)
: xs.concat
( scan(x.slice(0, -1))
, scan(x.slice(1))
);
return [...new Set(scan(str))];
};
console.log(find_palindromes("kayak").join());
console.log(find_palindromes("kayakkayak").join());
console.log(find_palindromes("kayakcanoe").join());
console.log(find_palindromes("kayam").join());
console.log(find_palindromes("appal").join());
console.log(find_palindromes("madamimadam").join());
console.log(find_palindromes("madamimadamkayak").join());
这是一个类似于 CertainPerformance 的答案,但对辅助函数使用递归:
const getSubstrings = (str) =>
str .length == 0
? []
: [
... str .split ('') .map ((_, i) => str .slice (0, str .length - i)),
... getSubstrings (str .slice (1))
]
const isPalindrome = (str) =>
str .length < 2
? true
: str [0] === str .slice (-1) [0] && isPalindrome (str .slice (1, -1))
const getPalindromicSubstrings = (str) =>
getSubstrings (str)
.filter (s => s.length > 1)
.filter (isPalindrome)
const countPalindromicSubstrings = (str) =>
getPalindromicSubstrings (str) .length
const countUniquePalindromicSubstrings = (str) =>
new Set(getPalindromicSubstrings (str)) .size
console .log (getPalindromicSubstrings ('madamimadam'))
console .log (countPalindromicSubstrings ('madamimadam'))
console .log (countUniquePalindromicSubstrings ('madamimadam'))
.as-console-wrapper {max-height: 100% !important; top: 0}
getSubstrings
正是您所期望的。 getSubstrings('abcd')
returns ["abcd", "abc", "ab", "a", "bcd", "bc", "b", "cd", "c", "d"]
.
isPalindrome
表示空字符串和单字符字符串自动回文,对于另一个字符串,我们检查两个结束字符匹配,在剩余部分重复出现。
getPalindromicSubstrings
查找所有回文子串,跳过长度为 1
.
的子串
countPalindromicSubstrings
returns 数一数。
countUniquePalindromicSubstrings
使用 Set
过滤掉重复项和 returns 计数。
如果需要,我们也可以用类似的方式轻松编写 getUniquePalindromicSubstrings
。
getSubstrings
是唯一具有任何复杂性的函数。它通过重复将我们的字符串切片为从 length
到 1
的值,然后在以第二个字符开始的字符串上重复出现,当我们的输入为空时停止。
我有一个检查字符串是否为回文的递归函数,但我的作业要求我计算字符串中回文的数量(例如 kayak 有 2 个)。
我真的很困惑如何实现一个计算回文数的递归函数。这是我当前的代码:
function isPalindrome(string) {
if (string.length <= 1) {
return true;
}
let [ firstLetter ] = string;
let lastLetter = string[string.length - 1];
if (firstLetter === lastLetter) {
let stringWithoutFirstAndLastLetters = string.substring(1, string.length - 1);
return isPalindrome(stringWithoutFirstAndLastLetters);
} else {
return false;
}
}
一种方法是首先
getAllSubstrings('kayak').filter(str => str.length >= 2 && isPalindrome(str))
function getAllSubstrings(str) {
var i, j, result = [];
for (i = 0; i < str.length; i++) {
for (j = i + 1; j < str.length + 1; j++) {
result.push(str.slice(i, j));
}
}
return result;
}
function isPalindrome(string) {
if (string.length <= 1) {
return true;
}
let [ firstLetter ] = string;
let lastLetter = string[string.length - 1];
if (firstLetter === lastLetter) {
let stringWithoutFirstAndLastLetters = string.substring(1, string.length - 1);
return isPalindrome(stringWithoutFirstAndLastLetters);
} else {
return false;
}
}
console.log(
getAllSubstrings('kayak').filter(str => str.length >= 2 && isPalindrome(str))
);
我认为接受的答案实际上不起作用。它不会计算回文,除非它们位于字符串的中心,并且只要它们以相同的字母开头和结尾,就会计算不是回文的子字符串。 CertainPerformance 的答案可能会起作用,但我认为这会导致检查很多不需要检查的字符串。这是我想出的,我认为它适用于我添加的额外测试。
function countPalindromes(string) {
if (string.length <= 1) {
return 0;
}
count = 0
for ( var i = 0; i < string.length; i++ ) {
count += countPalindromesCenteredAt(string, i)
count += countPalindromesCenteredAfter(string, i)
}
return count
}
function countPalindromesCenteredAt(string, i) {
count = 0
for ( var j = 1; i-j>=0 && i+j < string.length; j++ ) {
if (string.charAt(i-j) === string.charAt(i+j)) {
count += 1
}
else {
return count
}
}
return count
}
function countPalindromesCenteredAfter(string, i) {
count = 0
for ( var j = 1; i-j>=0 && i+j < string.length; j++ ) {
if (string.charAt(i-j+1) === string.charAt(i+j)) {
count += 1
}
else {
return count
}
}
return count
}
console.log(countPalindromes("kayak"));
console.log(countPalindromes("aya"));
console.log(countPalindromes("kayakcanoe"));
console.log(countPalindromes("kcanoek"));
当函数得到回文时很容易:
- 记录输入
- 没有边缘再试一次
- 输入不超过三个字符时停止
"kayak" -> "aya"
如果输入不是回文,请递归尝试“两端”,例如使用 "kayam"
尝试同时使用 "kaya"
和 "ayam"
并继续...
当字符串为 3 个(或更少)字符时,我们将停止递归。单个字符不是回文,检查两个或三个字符的字符串是否是回文是微不足道的。
kayam
|
+-------------+
| |
kaya ayam
| |
+-------+ +--------+
| | | |
kay aya aya yam
const reverse =
([...xs]) =>
xs.reverse().join("");
const is_palindrome =
a =>
a.length === 1 ? false
: a.length <= 3 ? a[0] === a[a.length-1]
: a === reverse(a);
const find_palindromes = str => {
const scan =
(x, xs = []) =>
x.length <= 3 ? xs.concat(is_palindrome(x) ? x : [])
: is_palindrome(x) ? xs.concat
( x
, scan(x.slice(1, -1))
)
: xs.concat
( scan(x.slice(0, -1))
, scan(x.slice(1))
);
return [...new Set(scan(str))];
};
console.log(find_palindromes("kayak").join());
console.log(find_palindromes("kayakkayak").join());
console.log(find_palindromes("kayakcanoe").join());
console.log(find_palindromes("kayam").join());
console.log(find_palindromes("appal").join());
console.log(find_palindromes("madamimadam").join());
console.log(find_palindromes("madamimadamkayak").join());
这是一个类似于 CertainPerformance 的答案,但对辅助函数使用递归:
const getSubstrings = (str) =>
str .length == 0
? []
: [
... str .split ('') .map ((_, i) => str .slice (0, str .length - i)),
... getSubstrings (str .slice (1))
]
const isPalindrome = (str) =>
str .length < 2
? true
: str [0] === str .slice (-1) [0] && isPalindrome (str .slice (1, -1))
const getPalindromicSubstrings = (str) =>
getSubstrings (str)
.filter (s => s.length > 1)
.filter (isPalindrome)
const countPalindromicSubstrings = (str) =>
getPalindromicSubstrings (str) .length
const countUniquePalindromicSubstrings = (str) =>
new Set(getPalindromicSubstrings (str)) .size
console .log (getPalindromicSubstrings ('madamimadam'))
console .log (countPalindromicSubstrings ('madamimadam'))
console .log (countUniquePalindromicSubstrings ('madamimadam'))
.as-console-wrapper {max-height: 100% !important; top: 0}
getSubstrings
正是您所期望的。getSubstrings('abcd')
returns["abcd", "abc", "ab", "a", "bcd", "bc", "b", "cd", "c", "d"]
.isPalindrome
表示空字符串和单字符字符串自动回文,对于另一个字符串,我们检查两个结束字符匹配,在剩余部分重复出现。
的子串getPalindromicSubstrings
查找所有回文子串,跳过长度为1
.countPalindromicSubstrings
returns 数一数。countUniquePalindromicSubstrings
使用Set
过滤掉重复项和 returns 计数。
如果需要,我们也可以用类似的方式轻松编写 getUniquePalindromicSubstrings
。
getSubstrings
是唯一具有任何复杂性的函数。它通过重复将我们的字符串切片为从 length
到 1
的值,然后在以第二个字符开始的字符串上重复出现,当我们的输入为空时停止。