Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 最近回文数_C++_Algorithm_Palindrome - Fatal编程技术网

C++ 最近回文数

C++ 最近回文数,c++,algorithm,palindrome,C++,Algorithm,Palindrome,我遇到了一个常见的面试问题,那就是找到最接近的回文数字。假设输入为127,则输出为131;如果输入为125,则输出为121 我能想出逻辑,但我的逻辑在某些情况下失败,比如91、911。在这些输入中,它给出了99919,但正确的输出是88和909 算法步骤如下: 将数字转换为字符串 按相反顺序将上半部分复制到下半部分 转换为数字并测量abs。与原始数字diff1的差异 将1添加到字符串的一半,然后按相反顺序将前一半复制到后一半 转换为数字并测量abs。与原始数字diff2的差异 如果diff1小

我遇到了一个常见的面试问题,那就是找到最接近的回文数字。假设输入为127,则输出为131;如果输入为125,则输出为121

我能想出逻辑,但我的逻辑在某些情况下失败,比如91、911。在这些输入中,它给出了99919,但正确的输出是88和909

算法步骤如下:

  • 将数字转换为字符串
  • 按相反顺序将上半部分复制到下半部分
  • 转换为数字并测量abs。与原始数字diff1的差异
  • 将1添加到字符串的一半,然后按相反顺序将前一半复制到后一半
  • 转换为数字并测量abs。与原始数字diff2的差异
  • 如果diff1小于diff2,则返回第一个数字,否则返回第二个数字

这里有一个通用算法,虽然使用蛮力,但仍然有效:

int findNearestPalindrome(int n) {
    int less = n;
    int more = n;
    while(true) {
        if (isPalindrome(less)) return less;
        if (isPalindrome(more)) return more;
        --less;
        ++more;
   }
}
isPalindrome()
函数中,您只需将数字转换为字符串,然后单击


1然而,这不会像Ted Hopp评论的那样检查平局情况。您必须进行一些更改以使其易于识别。

这实际上是一个有趣的问题。显然,要让这不仅仅是一种暴力,你要做的是使用最重要的数字,并把它们放在最不重要的数字位置,形成一个回文。(我将回文和原文之间的差异称为“距离”)

因此,我想说,我们可以忽略其中最不重要的一半,因为这真的不重要(在确定距离时很重要,但仅此而已)

我要取一个抽象数字:
ABCDEF
。其中A、B、C、D、E、F均为随机数字。正如我所说的,确定回文不需要D,E,F,因为我们想要的是将数字的前半部分镜像到后半部分。很明显,我们不想反过来做,否则我们会修改更重要的数字,导致与原始数字的距离更大

所以回文应该是ABCCBA
ABCCBA
,但是正如你已经说过的,这并不总是你最短的距离。然而,“解决方案”的形式仍然是
xyzyx
,因此,如果我们考虑最小化我们正在修改的数字的“重要性”,这意味着我们想要修改C(或最中间的数字)

让我们回顾一下原因:
ABCCBA

  • 起初,修改
    A
    可能很有诱惑力,因为它位于最不重要的位置:最右边。然而,为了修改最不重要的,我们需要修改最重要的。所以
    A
    退出了
  • 这同样适用于
    B
    ,因此
    C
    最终成为我们的首选数字
好的,现在我们已经计算出,我们想要修改
C
,以得到可能更接近的数字,我们需要考虑边界
ABCDEF
是我们的原始数字,如果
ABCCBA
不是最接近的回文,那么会是什么?基于我们上面的小迂回,我们可以通过修改
C
找到它。因此有两种情况,
ABCDEF
大于
ABCCBA
或小于
ABCCBA

如果
ABCDEF
大于
ABCCBA
,那么让我们将1添加到
C
。我们会说
T=C+1
,所以现在我们有一个数字
ABTTBA
。因此,我们将进行测试以确保
ABCDEF-ABCCBA>ABCDEF-ABTTBA
如果是这样,我们知道ABTTBA是最近的回文。因为对C的任何修改都会使我们越来越疏远

或者,如果
ABCDEF
小于
ABCCBA
,那么我们将从
C
中减去1。比如说
V=C-1
。所以我们有
ABVVBA
,就像上面我们要测试的:
ABCDEF-ABCCBA>ABCDEF-ABVVBA
,您将得到相同的解决方案

诀窍是
ABCDEF
总是介于
ABTTBA
ABVVBA
之间,这些数字之间唯一的其他回文是
ABCCBA
。因此,对于一个解决方案,您只有3个选项。如果您将
ABCDEF
ABCCBA
进行比较,则只需勾选2

我不认为这将是你很难适应任何规模的数字。在奇数位数的情况下,你只需要有
ABCBA
ABVBA
ABTBA
等等

就像你们的例子一样,让我们以911为例

  • 忽略最后一个1我们只做上半场(总结)。所以91X
  • 将X替换为9。我们有919辆。这是中点
  • 我们知道原来的911小于919,所以从中间数减去1,我们得到第二个(下限)909
  • 比较
    911-919
    911-909
  • 返回差异最小的一个
  • 这给了我们一个恒定时间算法:) 正如评论中指出的,这不是最坏情况下的恒定时间(oops),但肯定比暴力方法要好


    这似乎就是你所拥有的,但我想我会详细阐述,希望能阐明这个问题,因为这似乎是你的一个小编程错误。

    这是Naveen和Don算法的实现。它使用Happy Yellow Face的算法作为测试预言

    我会很高兴看到人们调整它,以消除多余的步骤或特殊情况

    gcc 4.7.3:g++-Wall-Wextra-std=c++0x最近回文.cpp

    #include <algorithm>
    #include <cassert>
    #include <iostream>
    #include <iterator>
    #include <sstream>
    #include <string>
    #include <vector>
    
    // I do not have std::to_string.
    template <class T>
    std::string to_string(const T& v) {
      std::stringstream ss;
      ss << v;
      return ss.str(); }
    
    // Nor do I have std::stoi. :(
    int stoi(const std::string& s) {
      std::stringstream ss(s);
      int v;
      ss >> v;
      return v; }
    
    bool isPalindrome(int n) {
      const auto s = to_string(n);
      return s == std::string(s.rbegin(), s.rend()); }
    
    int specNearestPalindrome(int n) {
      assert(0 <= n);
    
      int less = n, more = n;
      while (true) {
        if (isPalindrome(less)) { return less; }
        if (isPalindrome(more)) { return more; }
        --less; ++more; } }
    
    std::string reflect(std::string& str, int n) {
      std::string s(str);
      s.resize(s.size() + n);
      std::reverse_copy(std::begin(str),
          std::next(std::begin(str), n),
          std::next(std::begin(s), str.size()));
      return s; }
    
    bool isPow10(int n) {
      return n < 10 ? n == 1 : (n % 10 == 0) && isPow10(n / 10); }
    
    int nearestPalindrome(int n) {
      assert(0 <= n);
      if (n != 1 && isPow10(n)) { return n - 1; }  // special case
    
      auto nstr = to_string(n);
      // first half, rounding up
      auto f1 = nstr.substr(0, (nstr.size() + 1) / 2);
      auto p1 = stoi(reflect(f1, nstr.size() / 2));
    
      const auto twiddle = p1 <= n ? 1 : -1;
      auto f2 = to_string((stoi(f1) + twiddle));
      auto p2 = stoi(reflect(f2, nstr.size() / 2));
    
      if (p2 < p1) { std::swap(p1, p2); }
      return n - p1 <= p2 - n ? p1 : p2; }
    
    int main() {
      std::vector<int> tests = { 0, 1, 6, 9, 10, 11, 12, 71, 74, 79, 99, 100, 999, 1000, 9900, 9999, 999000 };
    
      for (const auto& t : tests) {
        std::cout <<
          (nearestPalindrome(t) == specNearestPalindrome(t) ? "." : "X");
      }
      std::cout << std::endl;
    
      return 0; }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    //我没有std::to_字符串。
    模板
    标准::字符串到_字符串(常量T&v){
    std::stringstream-ss;
    ss>v;
    返回v;}
    布尔伊斯帕林德罗姆(国际北){
    const auto s=到字符串(n);
    返回s==std::string(s.rbegin(),s.rend());}
    内部规范
    
    class Solution {
        public String nearestPalindromic(String n) {
             int order = (int) Math.pow(10, n.length()/2);
        Long ans = Long.valueOf(new String(n));
        Long noChange = mirror(ans);
        Long larger = mirror((ans/order)*order + order+1);
        Long smaller = mirror((ans/order)*order - 1 );
        if ( noChange > ans) {
            larger = (long) Math.min(noChange, larger);
        } else if ( noChange < ans) {
            smaller = (long) Math.max(noChange, smaller); 
        }       
        return String.valueOf( ans - smaller <= larger - ans ? smaller :larger) ;
    }
    Long mirror(Long ans) {
        char[] a = String.valueOf(ans).toCharArray();
        int i = 0;
        int j = a.length-1;
        while (i < j) {
            a[j--] = a[i++];
        }
        return Long.valueOf(new String(a));
    } 
    
    
    }
    
    #include <iostream>
    #include <cmath>
    #include <functional>
    #include <limits>
    #include <sstream>
    
    // for convience
    using namespace std; 
    using ULL = unsigned long long int;
    
    // calculate the number of digits
    auto Len = [](auto num) -> ULL {
    return floor(log10(num)) + 1; };
    
    // extract left half of number
    auto Halfn = [](auto num, auto olen) {
    for (unsigned i = 0; i < olen / 2; num /= 10, ++i);
     return num; 
    };
    
    int main() {   
    ULL num;   cin >> num;
    // some basic checking   
    if (num < 10)   {
    cerr << "Error, enter a number >= 10";
    return 0;   
    }
    
    if (numeric_limits<ULL>::max() <  num) {
    cerr << "Error, number too large\n";
    return 0;   
    }
    cout << ([](auto num) {   
    auto olen = Len(num);   
    auto lhalf = Halfn(num, olen);   
    
    function<ULL(ULL)> palin = [olen]  (auto lhalf) { 
    auto half = to_string(lhalf);
    // this is the mirror string that needs to be  
    // appended to left half to form the final 
    // palindrome 
    auto tmp = half.substr(0, olen / 2);
    
    // take care of a corner case which 
    // happens when the number of digits in 
    // the left half of number decrease, while
    // trying to find a lower palindrome 
    // e.g.  num = 100000
    // left half = 100  , the value passed to the  
    // function palin, is 99. if all digits  are 9 
    // then we need to adjust the   count of 9, 
    // otherwise if i simply replicate it, i'll get 
    // 9999 but one more 9 is required for the   
    // correct output.
    
    if (olen / 2 > tmp.size() &&
    all_of(tmp.begin(), tmp.end(),
    [](auto c) { return '9' == c; }))  {
    tmp += '9';  
    }
    
    // append, convert and return   
    half = half + string(tmp.crbegin(),                              
                       tmp.crend());
    return stoull(half);  
    };
    
    auto bpalin = palin(lhalf);   
    auto hpalin = palin(lhalf + 1);   
    auto lpalin = palin(lhalf - 1);
    
    stringstream ss;
    ss << "base palindrome = " << bpalin <<'\n'; 
    ss << "higher palindrome = "<<hpalin <<'\n';
    ss << "lower palindrome = " << lpalin  <<'\n';
    
    // calculating absolute difference for 
    // finding the nearest palindrome
    
    auto diffb = labs(bpalin - num);   
    auto diffh = labs(hpalin - num); 
    auto diffl = labs(lpalin - num);
    
    auto nearest = (diffb < diffh) ? 
    (diffb < diffl) ? bpalin : lpalin : 
    (diffh < diffl) ? hpalin : lpalin;
    
    ss << "nearest palindrome = "
         << nearest << endl;
        return move(ss.str());
     }(num)); 
    } // end main