找到给定回文日期的最近回文日期

时间:2015-02-24 16:10:34

标签: c algorithm palindrome

给出了回文日期,我们必须找到这个给定日期最近的回文日期。结果日期应该在给定日期之前。

日期的格式为YYYY/MM/DD

一个强力解决方案是(给出伪代码可能效率不高)。

Convert the string into a number
For each number less than this number
   If the number is a valid date then
    If number is a palindrome
         print and return

我认为必须有一些有效的算法来解决这个问题。

示例:输入日期:2030/03/02

输出日期:2021/12/02

2 个答案:

答案 0 :(得分:1)

如果您认为回文日期写为YYYY / MM / DD,如2121/12/12,您可以得出一些结论:

一个月中的一天是01到31之间,一个月是01到12.所以你推断出一个日期回文与下面的正则表达式匹配:

([0-9][0-2]|[01]3)([0-9]0|[12]1)-(0[0-9]|1[12])-([0-2][0-9]|3[01])
       1.  & 2.         3 & 4           4 & 3           2 & 1

我已经标记了重复的四个字母

输入日期前的回文将是

  • 如果可能的话减少n°4(去年和前一个月)

或者

  • 如果可能的话减少数量n°3(10年和1个月前)

或者

  • 如果可能的话减少数量n°2(100年和10天前)

  • 如果可能的话,减少数量n°1(1000年和1天前)

或者

停止

答案 1 :(得分:1)

在给定的一年中,只有一个回文日期。因此,要找到以前的回文日期,您需要递减年份并将其转换为回文日期。

示例:对于2030年,有效的月份和日期将是03和02,这将导致2030/03/02。

因此,必须明确的是,在这种情况下,只有在以下情况下才能使用回文日期:

  1. 年份是4位数(不是10000),因为月份和天数是两位数
  2. 年份的最后两位数应为{10,20,30,40,50,60,70,80,90,01,11,21}
  3. 年份的前两位数应为1-31的镜像(月和年有效期)。
  4. 使用规则2和3,可以在O(1)中检查给定年份是否具有给定格式的回文日期。让我们假设有效年份范围是9999-0001,那么它可以按线性顺序完成,以找到以前的回文日期。

    void find_prev_date(const char* input, char * output) {
        int year = extract_year(input); //Extract first 4 digits
        --year;
        //limit is 101 because 0000 will not give you valid month and day.
        for(;year>=101;--year) {
          if(haspalindromic(year))
          {
            write_date(year, output);
          }
        }
    }
    
    bool haspalindromic(int year)
    {
       int first2 = year%100;
       int last2 = year/100;
       bool second_valid = false;
       bool first_valid = false;
    
       switch(last2){
           case 10: case 20: case 30: case 40: case 50: case 60: case 70: case 80:
           case 90: case 1: case 11: case 21: second_valid = true; break;
       }
       if(!second_valid)
          return false;
    
       switch(first2) {
          case 10: case 20: case 30: case 40: case 50: case 60: case 70: case 80: case 90: case 1: case 11: case 21: case 31: case 41:    case 51: case 61: case 71: case 81: case 91:
          case 2: case 12: case 22: case 32: case 42: case 52: case 62: case 72: case 82: case 92:
          case 3: case 13:
             first_valid = true;
          break;
       }
    
       if(!first_valid)
          return false;
    
       //reverse digit such that 2 yields 20
       int month = reverse_digits_on100(last2);
       int day = reverse_digits_on100(first2);
    
       if(month==2) {
          if(day<=28)
             return true;
          if(isleapyear(year) && day==29)
             return true;
          if(day>28)
            return false;
       }
    
       switch(month) {
            case 4: case 6: case 9: case 11:
            if(day>30)
               return false;
       }
       //For remaining months, check is already made as first part of year is gives day in range of [1..31].
       return true;
    }
    

    某些功能尚未实施,但其名称明确暗示意图。