找到小于限制的数字排列中的最大可能数字

时间:2017-01-09 08:02:04

标签: c# algorithm

我想以一种结果是最大可能排列的方式来置换int的数字。这很容易做到:

//how to deal with really large ints e.g.int32.MaxValue goes here 
// in this case the algorithm would need to round down to the largest possible value 
// but still needs to be less than int32.MaxValue 
//This code will just handle normal values <int32.MaxValue 
public static int Max(int number)
{
    var numberAsCharArray = number.ToString().OrderByDescending(c => c).ToArray();
    var largestNumberAsString = new string(numberAsCharArray);
    return Int32.Parse(largestNumberAsString);
}

但是,当输入与Int32.MaxValue具有相同的位数并且包含至少一个高位时,该数字将转到第一个位置,使得结果&gt; Int32.MaxValue并在转换为int时导致异常。

如何将结果限制为&lt; = Int32.MaxValue但在此限制范围内仍然是最大可能的排列?

N.B。 否定号码,例如-1234567890被允许,也被允许;如果否定输入,则应删除-符号:-1234567890应生成2147398650输出

2 个答案:

答案 0 :(得分:2)

对于小数字(小于或等于1000000000),您可以照常开展业务;数字大于10亿 你可以尝试以下方法:

  1. 尝试遵循int.MaxValue模式(2147483647),只要可能
  2. 如果不可能,请填写您可以执行的最大数量,并继续照常开展剩余数字业务。
  3. 例如,给定1234567890

      1234567890 <- initial value
      2147483647 <- int.MaxValue pattern
      2147398650 <- solution
          ^
          |
          Here we can't put another 4, we put maximum available - 3
    
      Remaining digits [56890] we order by descending - "98650" - business as usual
    

    实施

    private static int Biggest(int value) {
      // Special MinValue case; 
      // we can't do Math.Abs() because of integer overflow
      if (value == int.MinValue)
        return 2147483486;
    
      string st = value.ToString().Trim('-');
    
      if (value <= 1000000000 && value >= -1000000000)
        return int.Parse(string.Concat(st.OrderByDescending(c => c)));
    
      string max = int.MaxValue.ToString();
    
      List<int> digits = st.Select(c => c - '0').ToList();
    
      StringBuilder sb = new StringBuilder(9);
    
      bool exact = true;
    
      while (digits.Any()) {
        for (int i = 0; i < max.Length; ++i) {
          int digitToFind = max[i] - '0';
    
          int digitActual;
    
          digitActual = digits
            .Where(d => !exact || d <= digitToFind)
            .OrderByDescending(d => d)
            .First();
    
          if (exact)
            exact = digitActual == digitToFind;
    
          sb.Append(digitActual);
    
          digits.Remove(digitActual);
        }
      }
    
      return int.Parse(sb.ToString());
    }
    

    测试:

    // 2147398650 (for reference: int.MaxValue == 2147483647)
    Console.WriteLine(Biggest(1234567890));
    

答案 1 :(得分:0)

我建议:

int number = 587;
int maximum = Int32.MaxValue;
var result = "";
if(number == Int32.MinValue)
{
    result = "2147483486";
}
else
{ 
    // create list of available digits removing - sign from the string
    var inputDigits = number.ToString().Replace("-", String.Empty).Select(c => Int32.Parse(new string(c, 1))).ToList();
    var limitDigits = maximum.ToString().Select(c => Int32.Parse(new string(c, 1))).ToList();
    var orderedDigits = inputDigits.OrderByDescending(c => c).ToList();
    int position = 0;
    // we only have to compare to the maximum if we have at least the same amount of digits in the input.
    bool compareValues = limitDigits.Count <= inputDigits.Count;
    // while we have not used all of the digits
    while (orderedDigits.Count > 0)
    {
        // loop over the remaining digits from high to low values
        for (int i = 0; i < orderedDigits.Count; i++)
        {
            // if it is above the digit in the maximum at the corresponding place we may only use it if input is shorter than maximum or if we have already used a lower value in a previous digit.
            if (orderedDigits[i] > limitDigits[position])
            {
                if (compareValues)
                {
                    continue;
                }
            }
            else if (orderedDigits[i] < limitDigits[position])
            {
                // remember that we have already used a lower value
                compareValues = false;
            }
            result += (orderedDigits[i].ToString());
            orderedDigits.RemoveAt(i);
            break;
        }
        position++;
    }
}
var intResult = Int32.Parse(result);

编辑:

在定义.Replace("-", String.Empty)以支持负数时插入inputDigits