C# 使用最大排列对数字进行排序

C# 使用最大排列对数字进行排序,c#,sorting,C#,Sorting,我想对整数列表进行排序,使它们尽可能分散。假设基数为8,1和7之间的项目顺序应为:{4,6,2,7,1,5,3},根据: 当然,有相当多的歧义,因为6和2与4、0和8的距离相等,所以6和2的具体顺序是不相关的。我试图实现的是首先选择距离0和基数最远的数字,然后选择距离0、基数和第一个数字最远的数字,等等。基数的任何倍数都不会出现,所以我不在乎如何处理 我可以为任何给定的基手动设计排序顺序,但我需要它来为任何大于等于2的基工作。有没有一种聪明/快速的方法来计算这个问题,或者我需要懒洋洋地构建排序

我想对整数列表进行排序,使它们尽可能分散。假设基数为8,1和7之间的项目顺序应为:{4,6,2,7,1,5,3},根据:

当然,有相当多的歧义,因为6和2与4、0和8的距离相等,所以6和2的具体顺序是不相关的。我试图实现的是首先选择距离0和基数最远的数字,然后选择距离0、基数和第一个数字最远的数字,等等。基数的任何倍数都不会出现,所以我不在乎如何处理

我可以为任何给定的基手动设计排序顺序,但我需要它来为任何大于等于2的基工作。有没有一种聪明/快速的方法来计算这个问题,或者我需要懒洋洋地构建排序映射表并缓存它们以备将来使用

int SortOrder(int radix, int value)
{
  int offset = value % radix;     
  int[] table = {int.MinValue, 4, 2, 6, 0, 5, 1, 3}; // Hand-crafted for base-8
  return table[offset];
}

我最初的答案是找到最大增量。要从“出”到“入”,请使用相同的比较但不同的选择:

 List<double> answer = new List<double>();
        List<double> doub = new List<double>() { 0, -1, 2, 3, 4, -5, 7 };//SORT this list for sorted results!
        List<double> lowerHalf = new List<double>();
        List<double> upperHalf = new List<double>();
        for (int i = 0; i < doub.Count; i++)
        {
            if (i <= (int)Math.Floor((double)doub.Count / 2))
                lowerHalf.Add(doub[i]);
            else
                upperHalf.Add(doub[i]);
        }

        if (upperHalf.Count < lowerHalf.Count)
        {
            upperHalf.Insert(0,lowerHalf[lowerHalf.Count-1]);
        }
        //if(upperHalf[0]==lowerHalf[lowerHalf.Count-1]){double median = lowerHalf[lowerHalf.Count-1]+upperHalf[1])/2;lowerHalf[lowerHalf.Count-1] = median; upperHalf[0]=median;}//use Math.Round or Math.Floor/Ceiling if necessary
        for (int i = 0; i < lowerHalf.Count; i++)
        {
            double deltas = Math.Sqrt(Math.Pow(upperHalf[upperHalf.Count - (i + 1)] - lowerHalf[i], 2));
            answer.Add(deltas);
             Console.WriteLine("The answer for {1}, {2} is: {0}", deltas, lowerHalf[i], upperHalf[upperHalf.Count - (i+1)]);
        }



        Console.ReadLine();
或者是数学。Abs或者是一个测试,看看哪个更大——但是这应该给你一个如何开始的想法。如果号码在原始列表中不按顺序排列,也可以在选择之前调用orderby

字面上:

         List<double> doub = new List<double>() { 0, 1, 2, 3, 4, 5, 7 };
        double deltas = Math.Sqrt( doub.Select(p => Math.Pow(p - doub.First(), 2)).OrderBy(p => p).Last());
        Console.WriteLine("The answer is: {0}",deltas);
        Console.ReadLine();
答案是:7

要继续对列表进行排序,请使用:

 List<double> answer = new List<double>();
        List<double> doub = new List<double>() { 0, 1, 2, 3, 4, 5, 7 };
        //sort doub if necessary
        foreach (double num in doub)
        {
            double deltas = Math.Sqrt(Math.Pow(doub.Select(p => p - num).OrderBy(p => p).Last(), 2));
            answer.Add(deltas);
            Console.WriteLine("The answer for {1} is: {0}", deltas,num);
        }
        Console.ReadLine();
平方/平方根有助于我们改变符号和处理消极因素——所以

 List<double> doub = new List<double>() { 0, -1, 2, 3, 4, -5, 7 };
因为我未能在入站或出站端对列表进行排序,所以没有按顺序排列

运行后,列表答案将包含结果-答案可以访问最低的增量。第一个,答案可以访问最高的增量。最后一个。类似的delta将存在于不同的数字和相同的单位数之间——如果您想消除重复的delta,可以在公式中使用HashSet转换。如果你需要帮助,请告诉我

如果需要存储创建增量的数字以及增量本身,则可以在For/Each循环中使用它们,如Console.WriteLine所示

如果您想在中间带的两侧计算到中间带的范围,最好将列表拆分并成对计算。在一个列表中,将0设为中间值,在第二个列表中,将中间值设为endRange,在第一个列表中计算,在第二个列表中计算。这会让你达到目的,但如果你需要帮助克服最后的困难,请告诉我


希望这有帮助

这并不是问题的答案,因为它不会试图快速找到答案。而是为每个基数构建缓存排序值的字典

#region sorting logic
/// <summary>
/// Maintains a collection of sorting maps for all used number bases.
/// </summary>
private static readonly Dictionary<int, int[]> _sortingTable = new Dictionary<int, int[]>();
private static readonly object _sortingLock = new object();

/// <summary>
/// Compute the sorting key for a given multiple.
/// </summary>
/// <param name="radix">Radix or base.</param>
/// <param name="multiple">Multiple.</param>
/// <returns>Sorting key.</returns>
public static int ComputeSortingKey(int radix, long multiple)
{
  if (radix < 2)
    throw new ArgumentException("Radix may not be less than 2.");

  if (multiple == 0)
    return int.MinValue; // multiple=0 always needs to be sorted first, so pick the smallest possible key.

  int[] map;
  if (!_sortingTable.TryGetValue(radix, out map))
    lock (_sortingLock)
    {
      map = new int[radix];
      map[0] = -1; // Multiples of the radix are sorted first.

      int key = 0;
      HashSet<int> occupancy = new HashSet<int> { 0, radix };
      HashSet<int> collection = new HashSet<int>(1.ArrayTo(radix)); // (ArrayTo is an extension method in this project)
      while (collection.Count > 0)
      {
        int maxValue = 0;
        int maxDistance = 0;
        foreach (int value in collection)
        {
          int distance = int.MaxValue;
          foreach (int existingValue in occupancy)
            distance = Math.Min(distance, Math.Abs(existingValue - value));

          if (distance > maxDistance)
          {
            maxDistance = distance;
            maxValue = value;
          }
        }
        collection.Remove(maxValue);
        occupancy.Add(maxValue);
        map[maxValue] = key++;
      }

      _sortingTable.Remove(radix); // Just in case of a race-condition.
      _sortingTable.Add(radix, map);
    }

  long offset = multiple % radix;
  if (offset != 0)
    if (multiple < 0)
      offset = radix - (Math.Abs(multiple) % radix);

  return map[(int)offset];
}
#endregion

什么是p.First表示double?p.First是列表中要排序的第一项,在本例中为nums。nums.Select p=>p.First将从列表中的第一个项目中选择每个项目的增量列表。你可以运行它并检查b4 You dv-答案是7。恐怕你错了-请查看我运行的代码和我编辑的答案中的结果。这个更新的答案如何产生OP的预期结果4、6、2、7、1、5、3我也看不出它有什么帮助。一旦将4确定为距离0和8最远的值,则下一个要拾取的值必须考虑0、8和4。为集合中的每个值预先计算一组距离是没有用的。顺便说一句,我正在使用整数和长整数,而不是双倍整数。不确定这对您的方法是否重要,但至少Pow和Sqrt调用停止有意义。
 List<double> answer = new List<double>();
        List<double> doub = new List<double>() { 0, 1, 2, 3, 4, 5, 7 };
        //sort doub if necessary
        foreach (double num in doub)
        {
            double deltas = Math.Sqrt(Math.Pow(doub.Select(p => p - num).OrderBy(p => p).Last(), 2));
            answer.Add(deltas);
            Console.WriteLine("The answer for {1} is: {0}", deltas,num);
        }
        Console.ReadLine();
 'OilTracker.vshost.exe' (CLR v4.0.30319: OilTracker.vshost.exe): Loaded 'C:\Users\User\Documents\Visual Studio 2015\Projects\OilTracker\OilTracker\bin\Debug\TDA_Stream_Interface.dll'. Symbols loaded.
 The answer for 0 is: 7
 The answer for 1 is: 6
 The answer for 2 is: 5
 The answer for 3 is: 4
 The answer for 4 is: 3
 The answer for 5 is: 2
 The answer for 7 is: 0
 List<double> doub = new List<double>() { 0, -1, 2, 3, 4, -5, 7 };
 The answer for 0 is: 7
 The answer for -1 is: 8
 The answer for 2 is: 5
 The answer for 3 is: 4
 The answer for 4 is: 3
 The answer for -5 is: 12
 The answer for 7 is: 0
#region sorting logic
/// <summary>
/// Maintains a collection of sorting maps for all used number bases.
/// </summary>
private static readonly Dictionary<int, int[]> _sortingTable = new Dictionary<int, int[]>();
private static readonly object _sortingLock = new object();

/// <summary>
/// Compute the sorting key for a given multiple.
/// </summary>
/// <param name="radix">Radix or base.</param>
/// <param name="multiple">Multiple.</param>
/// <returns>Sorting key.</returns>
public static int ComputeSortingKey(int radix, long multiple)
{
  if (radix < 2)
    throw new ArgumentException("Radix may not be less than 2.");

  if (multiple == 0)
    return int.MinValue; // multiple=0 always needs to be sorted first, so pick the smallest possible key.

  int[] map;
  if (!_sortingTable.TryGetValue(radix, out map))
    lock (_sortingLock)
    {
      map = new int[radix];
      map[0] = -1; // Multiples of the radix are sorted first.

      int key = 0;
      HashSet<int> occupancy = new HashSet<int> { 0, radix };
      HashSet<int> collection = new HashSet<int>(1.ArrayTo(radix)); // (ArrayTo is an extension method in this project)
      while (collection.Count > 0)
      {
        int maxValue = 0;
        int maxDistance = 0;
        foreach (int value in collection)
        {
          int distance = int.MaxValue;
          foreach (int existingValue in occupancy)
            distance = Math.Min(distance, Math.Abs(existingValue - value));

          if (distance > maxDistance)
          {
            maxDistance = distance;
            maxValue = value;
          }
        }
        collection.Remove(maxValue);
        occupancy.Add(maxValue);
        map[maxValue] = key++;
      }

      _sortingTable.Remove(radix); // Just in case of a race-condition.
      _sortingTable.Add(radix, map);
    }

  long offset = multiple % radix;
  if (offset != 0)
    if (multiple < 0)
      offset = radix - (Math.Abs(multiple) % radix);

  return map[(int)offset];
}
#endregion