Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
数组(图形)中包含区域的Python算法 设置:_Python_Arrays_Algorithm_List - Fatal编程技术网

数组(图形)中包含区域的Python算法 设置:

数组(图形)中包含区域的Python算法 设置:,python,arrays,algorithm,list,Python,Arrays,Algorithm,List,可视化一个大的数字数组,其中每个数字表示条形图上的条形高度 例:[5,4,3,7,2,3,1,12] █ █ █ █ █ █ █ █ █ █ █ █ ██ █ █ ████ █ █ ██████ █ ████████ 分析: 这是前面数字的条形图。我需要找到的是图中包含的面积,以开放(或未填充)单元的数量表示 解决方案(第1部分): 为此,我做了一个算法来计算数组中的所有峰值 这将返回:[5,7

可视化一个大的数字数组,其中每个数字表示条形图上的条形高度

例:
[5,4,3,7,2,3,1,12]

       █
       █
       █
       █
       █
   █   █
   █   █
█  █   █
██ █   █
████ █ █
██████ █
████████
分析: 这是前面数字的条形图。我需要找到的是图中包含的面积,以开放(或未填充)单元的数量表示

解决方案(第1部分): 为此,我做了一个算法来计算数组中的所有峰值

这将返回:
[5,7,3,12]
以及另一个包含每个条目索引的列表,
[0,3,5,7]

对我们来说,只有三座重要的山峰可以找到这个地区。
5
7
12
。 然后我们可以像这样分解它

5和7之间的空地面积为(一般规则):

(([较大的索引]-[较小的索引]-[1])*[较小的值]-[所有B/W中的值]

因此,第一部分的区域将是
(2*5)-(4+3)
10-7
3
。这是有道理的,因为如果你看图表,你会发现有一个空的L形部分,你可以容纳3个单位的水,比如说,水不会溢出。 如果你在第二部分重复这个步骤,你也会得到正确的区域

我的问题是开发一种从
所有峰值
重要峰值
的算法。 误导: 在这种情况下,很容易看出如何做到这一点。您只需编写一个算法,就可以发现
3
7
12
小,因此请去掉它并返回峰值的优化版本

然而,它并不总是那么简单

更难的例子: 我有一个数组:

[5,4,3,7,2,3,1,12,9,10,5,3,6,8,5,6,4,7,6,9,4,11,4,1,2,1]

通过基本的自定义峰值查找算法运行它将返回:

[5,7,3,12,10,8,6,7,9,11,11,4,2]

在这个例子中,我们在问题的第一部分看到了相同的问题,但是,在这个峰值列表中的
12
之后,人们可以很容易地看到下一个最重要的峰值是两个
11s
4
2
。因此,我需要一种方法:

[5,7,3,12,10,8,6,7,9,11,11,4,2]

致:

[5,7,12,11,11,4,2]

上面的数组是一个“重要”峰的列表,这些峰是找到该区域和再次可视化开放区块所必需的,就像它们含有水或其他东西一样,因此它们在溢出之前被限制在最低点

为了更好地可视化这个更完整的第二个示例,我有一张图以及它的所有峰值和数据点的图片


谢谢。

您可以通过考虑两个值来解决此问题:

  • 到目前为止的最大峰值,从左侧开始
  • 到目前为止的最大峰值,从右侧开始

  • 如果峰值低于两者,不要接受它,因为它将在水下。

    我认为这可以处理所有条件,但对于大型数据集,所有的最大计算都会减慢它的速度。我用IPython笔记本画了它。这基本上是@Rémi的想法:

    对于任何数据点:

  • 将最大点移到左边,将最大点移到右边。 A.如果在两端假设为零
  • 取两个最大值中的最小值
  • 如果数据点低于该最小值,则该数据点在水下,否则返回差值为零
  • 它可以通过在向右扫描时计算左最大值,并在从右向左的单次扫描中提前计算每个位置的右最大值来进行优化

    按照目前的算法,在我的系统上执行10000个数据点大约需要4.1秒

    未填充区域(黄色)将为
    sum(C)

    %matplotlib内联
    将matplotlib.pyplot作为plt导入
    随机输入
    def贡献(L,i):
    如果i==0,则max_left=0,否则max(L[:i])
    如果i==len(L)-1否则max(L[i+1:]),则max\u right=0
    下=最小(左最大,右最大)
    如果较低值小于L[i],则返回0,否则返回较低值-L[i]
    N=[random.randint(0,12)表示范围(50)内的i]
    C=[范围(len(N))内i的贡献(N,i)]
    ind=列出(范围(len(N))#组的x个位置
    宽度=1#条的宽度:也可以是len(x)序列
    p1=plt.bar(长度,N,宽度,颜色='r')
    p2=plt.bar(ind,C,width,color='y',bottom=N)
    

    编辑 下面是一个更快的版本,它实现了我上面提到的优化。它在1.33秒内计算出100万个数据点,但在下面的图形中使用的数据点较少。考虑到一个细胞需要知道其左右最大值,并且在任何方向上都可能有多个点等于最大值,我不知道如何在一个过程中完成

    %matplotlib inline
    import matplotlib.pyplot as plt
    import random
    
    def right_maximums(L):
        '''Given list L, compute [max(L[i+1:] for i in range(len(L)-1)]+[0] more efficiently.
        
        This gives the maximum cell to the right of the current cell.
        Example: [1,2,3,4,5,4,3,2,1] -> [5,5,5,5,4,3,2,1,0]
        '''
        N = [0]
        for i,v in enumerate(L[:0:-1]):
            N.append(max(N[i],v))
        return N[::-1]
    
    def contribution(N):
        '''In a bar graph of data N, compute how much "water" a data valley, assuming water
        spills off the sides of the bar graph.
        '''
        rmaxs = right_maximums(N) # compute maximums to the right of a data point in advance.
        lmax = 0 # compute maximums to the left as we go.
        C = []
        for i,v in enumerate(N):
             # find the lower of the left and right maximum.
            lower = min(lmax,rmaxs[i])
            # if the data point is higher than the maximums, it won't hold water,
            # else it holds the difference between the lower maximum and its value.
            C.append(0 if lower < v else lower - v)
            lmax = max(lmax,v)
        return C
    
    N = [random.randrange(0,50) for i in range(50)]
    C = contribution(N)
    
    ind = list(range(len(N))) # the x locations for the groups
    width = 1                 # the width of the bars: can also be len(x) sequence
    
    p1 = plt.bar(ind, N, width, color='r')
    p2 = plt.bar(ind, C, width, color='y',bottom=N)
    
    %matplotlib内联
    将matplotlib.pyplot作为plt导入
    随机输入
    def右_最大值(L):
    ''给定列表L,更有效地计算范围(len(L)-1)+[0]内i的[max(L[i+1:]。
    这将使最大单元格位于当前单元格的右侧。
    示例:[1,2,3,4,5,4,3,2,1]->[5,5,5,4,3,2,1,0]
    '''
    N=[0]
    对于枚举中的i,v(L[:0:-1]):
    N.append(最大值(N[i],v))
    返回N[:-1]
    def贡献(N):
    ''在数据N的条形图中,假设有水,计算一个数据谷的“水”量
    从条形图的侧面溢出。
    '''
    rmaxs=右_最大值(N)#提前计算数据点右侧的最大值。
    lmax=0#在我们前进时计算左边的最大值。
    C=[]
    对于枚举(N)中的i,v:
    #找到左侧和右侧最大值中的较低值。
    下限=最小值(lmax,rmaxs[i])
    #如果数据点高于最大值,它就站不住脚,
    #否则,它将保留较低的最大值与其值之间的差值。
    C.追加(如果较低值%matplotlib inline
    import matplotlib.pyplot as plt
    import random
    
    def right_maximums(L):
        '''Given list L, compute [max(L[i+1:] for i in range(len(L)-1)]+[0] more efficiently.
        
        This gives the maximum cell to the right of the current cell.
        Example: [1,2,3,4,5,4,3,2,1] -> [5,5,5,5,4,3,2,1,0]
        '''
        N = [0]
        for i,v in enumerate(L[:0:-1]):
            N.append(max(N[i],v))
        return N[::-1]
    
    def contribution(N):
        '''In a bar graph of data N, compute how much "water" a data valley, assuming water
        spills off the sides of the bar graph.
        '''
        rmaxs = right_maximums(N) # compute maximums to the right of a data point in advance.
        lmax = 0 # compute maximums to the left as we go.
        C = []
        for i,v in enumerate(N):
             # find the lower of the left and right maximum.
            lower = min(lmax,rmaxs[i])
            # if the data point is higher than the maximums, it won't hold water,
            # else it holds the difference between the lower maximum and its value.
            C.append(0 if lower < v else lower - v)
            lmax = max(lmax,v)
        return C
    
    N = [random.randrange(0,50) for i in range(50)]
    C = contribution(N)
    
    ind = list(range(len(N))) # the x locations for the groups
    width = 1                 # the width of the bars: can also be len(x) sequence
    
    p1 = plt.bar(ind, N, width, color='r')
    p2 = plt.bar(ind, C, width, color='y',bottom=N)
    
      public static int areaContained(int[] arr) {
        int[] maxL = new int[arr.length];
        int[] maxR = new int[arr.length];
    
        int max = 0;
        for (int i = 0; i < arr.length; i++) {
          max = Math.max(arr[i], max);
          maxL[i] = max;
        }
    
        max = 0;
        for (int i = arr.length - 1; i >= 0; i--) {
          max = Math.max(arr[i], max);
          maxR[i] = max;
        }
    
        int total = 0;
        for (int i = 0; i < arr.length; i++) {
          int areaI = Math.min(maxL[i], maxR[i]) - arr[i];
          if (areaI > 0)
            total += areaI;
        }
    
        return total;
      }