【问题标题】:C#: A Bounding Max and Min on Array[]C#:Array[] 上的边界最大值和最小值
【发布时间】:2011-01-18 04:50:57
【问题描述】:

假设我有一个列表。我希望能够计算半等距离的最大和最小边界点。我不想简单地让 Max() 和 Min() 稍微复杂一些。

首先,我想在列表中指定一个可以划分列表的点。为了方便起见,假设该点为 0。然后我想指定分割数。示例:

List<int> Array = {-9,-8,-7,-2,-1,0,1,6,9,12};
int Divisions = 4;
int CutOff = 0;

因此,使用这些参数,我想从 0 开始走到极端,直到有 4 个分区。在这种情况下,DivisionSize 应该是 6。

因此,算法将从 0 开始,走到 -6 表示第 1 个分区,然后步行到 -12 表示第 2 个分区。然后-12 将成为该算法的边界最小值。

然后将通过从 0 开始并步行到 6,然后是 12 来计算 Max。然后边界 Max 将是 12。如果 Calculate Max 和 Min 是列表的实际 Max 和 Min 就可以了,这只是不太可能的情况。

我基本上在计算 DivisionSize 时遇到了一些问题。我从 (Abs(Max)+Abs(Min))/Divisions 开始,但我似乎无法得到需要扩展每个部门的计算大小以实际包含原始 Min 和 Max 的边缘情况。有人可以提供一些指导吗?

编辑:我不一定希望 BoundedMax 和 BoundedMin 关于截止点对称。我想在截止的任一侧添加松弛,直到 BoundedMin 和 BoundedMax >= 并且

【问题讨论】:

  • Abs(Max)-Abs(Min) 听起来很不对劲。你的意思是Abs(Max - Min)
  • 应该是+。固定的谢谢。
  • 必须是Abs(Max - Min)。考虑Max = 102Min = 98;分区大小将是 50,而实际上应该是 26。

标签: c# algorithm math


【解决方案1】:

由于您的分区将与截止点“半等距”,因此您的算法应该只关注一半的分区(截止点的一侧)。下一步将是确定截止的哪个“边”更大。
接下来,我们将较大的一侧除以除法的一半,并获得该值的上限(四舍五入到下一个更高的整数)。这将为我们提供较大边的每个分区的大小,其中将包含截止点两侧的所有值。
当应用于您提供的示例时,以下算法将为您提供 6 的 DivisionSize:

int NewMax = Abs(Max - CutOff);
int NewMin = Abs(Min - CutOff);
int DivisionSize = (int)Math.Ceiling(NewMax > NewMin ? NewMax/(Divisions/2) : NewMin/(Divisions/2));

【讨论】:

  • 不需要除以 2。我认为我没有充分表达我真正想要做的事情。
【解决方案2】:
L = abs(min(A)-cut)
R = abs(max(A)-cut)
size = max(L,R) # ate least two divisions
while divisions >= (1+(L-1)/size + 1+(R-1)/size)
    size = size-1
size = size+1

让我们试试吧:

L = 9
R = 12
size = 12
d = 1 + (9-1)/12 + 1 + (12-1)/12 = 1 + 1 = 2
size = 11
d = 1 + (9-1)/11 + 1 + (12-1)/11 = 1 + 2 = 3
size = 10
d = 1 + (9-1)/10 + 1 + (12-1)/10 = 1 + 2 = 3
size = 9
d = 1 + (9-1)/9 + 1 + (12-1) / 9 = 1 + 2 = 3
size = 8
d = 1 + (9-1)/8 + 1 + (12-1) / 8 = 2 + 2 = 4
size = 7 
d = 1 + (9-1)/7 + 1 + (12-1) / 7 = 2 + 2 = 4
size = 6
d = 1 + (9-1)/6 + 1 + (12-1) / 6 = 2 + 2 = 4
size = 5
d = 1 + (9-1)/5 + 1 + (12-1) / 5 = 2 + 3 = 5
--> size = 6

请注意,整数除法必须是底数(不是四舍五入)。

为了优化,您可以使用 1 和 R 之间的二进制搜索来获取大小。

【讨论】:

    【解决方案3】:

    我认为关键是通过取每一边的长度与总长度的比率来确定你想要在 CutOff 点的每一边有多少分割。

    在您的示例中,边是 9 和 12,每边给出(大约)1.7 和 2.2 的除法。实际数字必须是整数,因此请尝试 (1,3) 和 (2,2)。左侧 1 格表示大小必须为 9,两侧的 2 格允许您使用 6 格。

    写了一些 C# 来说明这一点。不是特别优雅,但它似乎有效。

    public class RangeDivider
    {
        public int Min;
        public int CutOff;
        public int Max;
        public int NumDivisions;
    
        public RangeDivider(int min, int cutOff, int max, int numDivisions)
        {
            Min = min;
            CutOff = cutOff;
            Max = max;
            NumDivisions = numDivisions;
            System.Diagnostics.Debug.Assert(Min < CutOff && CutOff < Max && numDivisions >= 2);
        }
    
        public int LeftSize { get { return CutOff - Min; } }
        public int RightSize { get { return Max - CutOff; } }
        public int WholeSize { get { return Max - Min; } }
    
        private static int divCeil(int dividend, int divisor) { return 1 + (dividend - 1)/divisor; }
    
        private int ReturnSize(int leftDivisions)
        {
            int rightDivisions = NumDivisions - leftDivisions;
            if (leftDivisions > 0 && rightDivisions > 0)
            {
                return Math.Max(divCeil(LeftSize, leftDivisions), divCeil(RightSize, rightDivisions));
            }
            else
            {   //Must have at least 1 division each side of cutoff
                return int.MaxValue;
            }
        }
    
        public int GetSize()
        {
            var leftDivisions = NumDivisions * LeftSize / WholeSize;
            var size =  Math.Min(ReturnSize(leftDivisions), ReturnSize(leftDivisions + 1));
            Console.WriteLine("Min {0}, CutOff {1}, Max {2}, NumDivisions {3} gives a Division Size of {4}", Min, CutOff, Max, NumDivisions, size);
            return size;
        }
    
        public static int Get(int min, int cutOff, int max, int numDivisions) 
        { 
            return new RangeDivider(min, cutOff, max, numDivisions).GetSize(); 
        }
    
        public static void Test()
        {
            Get(-7,0,57,4);
            Get(-9, 0, 12, 4);
            Get(-1, 0, 7, 6);
        }
    
    }
    
    • Min -7,CutOff 0,Max 57,NumDivisions 4 给出的分区大小为 19
    • Min -9,CutOff 0,Max 12,NumDivisions 4 给出的分区大小为 6
    • Min -1,CutOff 0,Max 7,NumDivisions 6 给出的分区大小为 2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-27
      • 2014-03-22
      • 2021-04-13
      • 2013-05-06
      • 2015-05-25
      • 2017-02-13
      • 1970-01-01
      • 2015-09-30
      相关资源
      最近更新 更多