假设您正在从字符流中读取,当您读取第一个回文出现时,函数应该返回。
回文的长度应为偶数。
时间复杂度要求为O(N)。
示例:
1. 第一个字符:4 2. 第二个字符:1 3. 第三个字符:3 4. 第四个字符:3 5. 第五个字符:1 6. 第六个字符:4,返回结果。
回文的长度应为偶数。
时间复杂度要求为O(N)。
示例:
1. 第一个字符:4 2. 第二个字符:1 3. 第三个字符:3 4. 第四个字符:3 5. 第五个字符:1 6. 第六个字符:4,返回结果。
p = 17 // or your lucky prime number
m = 10^9 // ...
hash = 0
hash_rev = 0
str = ''
str_rev = ''
p_pow = 1
while True
read c
append c to str
prepend c to str_rev
hash = (hash * p + c) mod m
hash_rev = (hash_rev + p_pow * c) mod m
p_pow = p_pow * p
if hash == hash_rev
if str == str_rev
found str to be the first palindrome
当你读到第一个字符时,请返回,即是单字母回文。
main()
{
string str = "";
char c1;
char c2;
while(true)
{
//has to be even, always get two chars at a time
c1 = GetCharFromStream();
c2 = GetCharFromStream();
str += c1 + c2;
if(isPalindrome(str))
{
Console.WriteLine(str);
return;
}
}
}
bool isPalindrome(string str)
{
if (str.Length % 2 != 0)
throw new InvalidArgumentException("str");
int first = 0;
int last = str.Length - 1;
while(first <= last)
{
if(str[first] != str[last])
return false;
first++;
last--;
}
return true;
}
使用Hashset怎么样?
假设输入流是1221
。
Hashset = empty;
if(hashset does not contain the inputelement)
{
add to hashset. // 12 will be in the hashset. //413 for your example.
}
else
{
delete from Hashset. // First deletes 2 and then 1. // First deletes 3, then 1 then 4.
if(hashset is empty)
return true; //Hashset is empty. return true.
}
class PalindromeDetector {
private static class DetectorImpl {
final ArrayList<Character> string = new ArrayList<Character>(32);
boolean addSymbol(char symbol) {
string.add(symbol);
return check();
}
private boolean check() {
if (string.size() < 2)
return false;
int lowBound = string.size() / 2 - 1;
int hiBound = lowBound + 1;
while (lowBound >= 0 && string.get(lowBound) == string.get(hiBound)) {
lowBound --; hiBound ++;
}
return lowBound == -1;
}
}
static boolean isPalindrome(String s) {
DetectorImpl detector = new DetectorImpl();
int index = 0;
while (index < s.length())
if (detector.addSymbol(s.charAt(index++)))
return true;
return false;
}
}
以下是用于该代码的单元测试:
@Test
public void test() {
assertFalse(PalindromeDetector.isPalindrome("4"));
assertTrue(PalindromeDetector.isPalindrome("44"));
assertFalse(PalindromeDetector.isPalindrome("4343"));
assertTrue(PalindromeDetector.isPalindrome("4334"));
assertFalse(PalindromeDetector.isPalindrome("41331"));
assertTrue(PalindromeDetector.isPalindrome("413314"));
}
好的,既然我的第一个答案时间复杂度是O(n^2)
,那么这里有另一个答案,时间复杂度为O(n)
,正如所请求的。
class PalindromeDetector {
private static class DetectorImpl {
int firstHalfSum, secondHalfSum;
int size = 0, tensPower = 1;
boolean add(int v) {
if (size % 2 == 1) {
firstHalfSum = firstHalfSum + (secondHalfSum / tensPower) * tensPower;
secondHalfSum = (secondHalfSum % tensPower) * 10 + v;
if (firstHalfSum == secondHalfSum)
return true;
} else {
secondHalfSum = secondHalfSum * 10 + v;
}
size ++;
if (size % 2 == 0)
tensPower *= 10;
return false;
}
}
static boolean isPalindrome(String s) {
if (s == null || s.length() == 0)
return false;
int val = Integer.parseInt(s);
int tensPower = s.length() == 1 ? 1 : (int) (Math.pow(10, s.length() - 1));
DetectorImpl detector = new DetectorImpl();
while (tensPower > 0) {
int digit = val / tensPower;
if (detector.add(digit))
return true;
val = val % tensPower;
tensPower /= 10;
}
return false;
}
}
这里是单元测试:
@Test
public void test() {
assertFalse(PalindromeDetector.isPalindrome("4113"));
assertTrue(PalindromeDetector.isPalindrome("3443"));
assertTrue(PalindromeDetector.isPalindrome("473374"));
assertTrue(PalindromeDetector.isPalindrome("413314"));
}
假设输入由十进制数字组成,但可以轻松扩展为包含字母数字的输入(只需假设英文字母+ 10个数字给我们提供了36进制的数字系统)。
这个解决方案(使用Haskell语言)依赖于一个观察结果,即偶数长度的回文串在其中心包含一个重复字符。当我们从输入流中读取字符时,我们测试这样的字符对,当找到一个时,我们就会生成一个新的候选答案。对于每个候选回文串,我们还保留一个“待匹配字符列表”,当读取每个新字符时,我们将其与该列表进行匹配 - 如果没有匹配,则丢弃该候选项。当匹配列表为空时,解决方案已经找到。请注意,尽管每个候选者都维护自己的匹配列表,但这些列表都只是同一列表的后缀,在Haskell中,即使有许多候选者,它们也将共享空间,并且总共不会占用超过O(n)的空间。
在最佳情况下,答案的中心只有一个成对字符,因此没有“误报”候选项,时间复杂度为O(n) - 每个字符最多被检查两次。对于具有许多错误开始的输入字符串,例如“abbbbbbbbbbbba”,我不确定时间复杂度 - 它可能不再是O(n),但它比O(n^2)更好,因为没有候选项的存活时间超过min(k, n-k)
,其中k
是候选项中心的位置。
filter_map::(a -> Maybe a)->[a]->[a]
filter_map op = foldr (maybeCons . op) []
where maybeCons Nothing ys = ys
maybeCons (Just y) ys = y:ys
-- Return the first prefix of the input argument that
-- is an even-length palindrome.
prefix_palindrome::(Eq a)=>[a]->[a]
prefix_palindrome (x:xs) = search [x] [] xs
where search seen ([]:_) _ = seen
search (s:seen) candidates (x:xs) | x == s = search seen' (candidates' ++ [seen]) xs
| otherwise = search seen' candidates' xs
where seen' = (x:s:seen)
candidates' = filter_map extend candidates
where extend (c:cs) | c == x = Just cs
| otherwise = Nothing