数组(图形)中包含区域的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的想法: 对于任何数据点:
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;
}