C#:数组[]上的边界最大值和最小值

时间:2011-01-18 04:50:57

标签: c# algorithm math

假设我有一个List。我希望能够计算半等距离的最大和最小边界点。我不想简单地让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将成为边界Min。

然后通过从0开始并且步行到6然后12来计算Max。然后,边界Max将是12.如果计算最大值和最小值是列表的实际最大值和最小值,这是正常的,这只是一个不太可能的案例。

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

编辑:我不一定希望BoundedMax和BoundedMin关于截止值对称。我想在截止的两边添加松弛,直到BoundedMin和BoundedMax为&gt; =&lt; = List的范围。

3 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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之间的二进制搜索作为大小。

答案 2 :(得分:0)

我认为关键是通过将每一边的长度与总长度的比率确定你想要的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