我的算法中获得最大回文的缺陷在哪里是一个数字的字符串表示?

时间:2016-08-08 15:10:23

标签: c# string algorithm linq

我试图获得可以通过k替换字符串number中的数字形成的最大回文。

e.g。

number="3943",k=1 --> "3993"

对于那个确切的测试用例,我得到"393",对于某些测试用例,我收到的错误如

  

未处理的异常:System.InvalidOperationException:Sequence   System.Linq.Enumerable.Last [TSource]中不包含任何元素   (IEnumerable`1 source)< 0x414ec920 + 0x001ab> in:0   在Solution.LargestPalindrome(System.String numstr,Int32 k)   [0x00197]在solution.cs中:74 at   解决方案+ c__AnonStorey0。<> m__0(System.String str)   solution.cs中的[0x00009]:61

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
    static bool IsPalindrome(string s)
    {
        // returns true or false depending on whether the string
        // s is a palindrome
        // e.g. "abba" --> true, "acba" --> false
        for(int i = 0, j = s.Length - 1; i < j; ++i, --j)
        {
            if(s[i] != s[j])
                return false;
        }
        return true;
    }

    static string Replace(string s, int i, char c)
    {
        // returns a copy of s with the character at index i
        // replaced by character c
        // e.g. "george",2,"x" --> "gexrge"
        string part1 = s.Length > 0 ? s.Substring(0, i) : string.Empty;
        string part2 = i < (s.Length - 1) ? c.ToString() : string.Empty;
        string part3 = (i + 1) < (s.Length - 1) ? s.Substring(i + 1, s.Length - i - 1) : string.Empty;
        return part1 + part2 + part3;
    }

    static string LargestPalindrome(string numstr, int k)
    {
        // numstr: string representation of number
        // k: maximum number of digit replacements allowed

        // if no digit replacements allowed, return same string
        if(k == 0)
            return numstr;

        // digrange will be {'0', '1', ..., '9'}
        List<char> digrange = new List<char>();
        for(char c = '0'; c <= '9'; ++c)
            digrange.Add(c);

        // possibilities will be all possibilities of replacing one digit from numstr
        // e.g. numstr="02" --> possibilities={"12","22","32",...,"92","00","01","03","09"}
        List<string> possibilities = new List<string>();        
        for(int i = 0; i < numstr.Length; ++i)
        {         
            foreach(char dig in digrange.Where(d => d != numstr[i]))
            {
                possibilities.Add(Replace(numstr,i,dig));
            }
        }

        // if k = 1, get all the strings in cumulativePossiblities that are palindromes; 
        // else, transform each into the largest palindrome formed by k - 1 character
        // replacements of itself
        var cumulativePossibilities =  k == 1 
            ? possibilities.Where(str => IsPalindrome(str))
            : possibilities.Select(str => LargestPalindrome(str, k - 1)).Where(str => IsPalindrome(str));

        // sort cumulativePossibilities in ascending order of the integer representation
        // of the strings
        cumulativePossibilities.ToList().Sort((s1,s2) => {
            Int64 i1 = Int64.Parse(s1),
                  i2 = Int64.Parse(s2);
            return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
        });

        // get the last element of the now-sorted cumulativePossibilities, 
        // which will be the largest number represented by the possible strings
        // or will be null if there are none
        string largest = cumulativePossibilities.Last();

        // return the largest or "-1" if there were none
        return largest != null ? largest : "-1";
    }

    static void Main(String[] args)
    {
        string[] tokens_n = Console.ReadLine().Split(' ');
        int k = Convert.ToInt32(tokens_n[1]);
        string number = Console.ReadLine();
        // use brute force algorithm to find largest palindrome of the string
        // representation of the number after k replacements of characters
        Console.WriteLine(LargestPalindrome(number,k));
    }
}

2 个答案:

答案 0 :(得分:0)

方法效率不高,但实施简单;关键功能是使用PalindromeSubstitutions(计算多少字符&#39;替换可防止字符串为回文)而不是IsPalindrome只是一个事实如果字符串是回文或不是)

// How many characters should be substituted in order to
// turn the string into palindrom
private static int PalindromeSubstitutions(string value) {
  if (string.IsNullOrEmpty(value))
    return 0;

  int result = 0;

  for (int i = 0; i < value.Length / 2; ++i)
    if (value[i] != value[value.Length - 1 - i])
      result += 1;

  return result;
}

// Let's test all substrings of size Length, Length - 1, ... , 2, 1
// until we find substring with required tolerance
private static string BestPalindromeSubstitutions(string value, int tolerance) {
  for (int size = value.Length; size >= 1; --size)
    for (int start = 0; start <= value.Length - size; ++start)
      if (PalindromeSubstitutions(value.Substring(start, size)) <= tolerance)
        return value.Substring(start, size);

  return "";
}

private static string SubstituteToPalindrome(string value) {
  if (string.IsNullOrEmpty(value))
    return value;

  StringBuilder sb = new StringBuilder(value);

  for (int i = 0; i < value.Length / 2; ++i) 
    sb[value.Length - 1 - i] = sb[i];

  return sb.ToString();
}

测试:

 string input = "73943";
 string best = BestPalindromeSubstitutions(input, 1);
 string report = 
   string.Format("Best palindrome {0} -> {1}", best, SubstituteToPalindrome(best));

输出

   Best palindrome 3943 -> 3993

答案 1 :(得分:0)

问题是贪婪算法的一个非常简单的例子。让我们首先计算需要多少排列(至少)将数字转换为回文数。

int req = 0;
for(int i = 0; i <= (s.length()-1)/2; i++){
    if (s[i] != s[s.length()-1-i] && i != s.length()-1-i) req++;
}

现在完成后,让我们再次从左到右依次检查数字:i经过0(s.length()-1)/2。考虑以下情况(这里i不是中间字母,我们单独考虑的情况):

  • s[i] == s[s.length()-i-1],它未计入req,因此如果k >= req + 2s[i] != '9',我们会将这两个字母更改为'9',并减少{{} 1}}由2,k保持不变。但请注意,我们保证有足够的操作来确保该号码可以变成回文(如果最初可能的话)
  • req - 现在如果s[i] != s[s.length()-i-1]或其中一个字母为k == req,请执行以下操作:'9'。按s[i]=s[s.length()-i-1]=max({s[i], s[s.length()-i-1]})减少kreq
  • 现在如果1且两个字母都不是k > req,我们会将它们都更改为'9'9k -= 2

现在,如果req -= 1i = s.length()-i-1,请将此字母k > 0更改为s[i]

你最终得到的结果是你正在寻找的。

总复杂度为'9'