我试图解决这个算法问题:在numpy数组中找到只有一个值的最大正方形。
示例图片:
我的代码耗费了太多时间。有没有办法提高速度?
import numpy as np
answer = 0
def allsame(board):
memory = board[0,0]
board = np.matrix(board)
for i in range(board[0].size):
for j in range(board[0].size):
if board[i,j] != memory: return False
return True
def findLargestSquare(board):
global answer
list = []
a = np.matrix(board)
if a[0].size == 1 or a[:,1].size==1: return answer
if a[1].size < a[:,1].size: ran = a[1].size
else: ran = a[:,1].size
for i in range(ran+1):
for j in range(ran+1):
if a[i:j,i:j].size > 0 and allsame(a[i:j,i:j])==True:
if a[i:j,i:j].size > answer:
list.append(a[i:j,i:j].size)
answer = a[i:j,i:j].size
findLargestSquare(a[1:])
return findLargestSquare(a[:,1:])
return answer
#testBoard = [['x','o','g'],['b','a','j'],['u','q','p']]
testBoard = [['X','O','O','O','X'],['X','O','O','O','O'],['X','X','O','O','O'],['X','X','O','O','O'],['X','X','X','X','X']]
print(findLargestSquare(testBoard))
我将我的代码更改为自卷积方法。 你能看看哪一部分是错的吗?
import numpy as np
import time
answer = 0
def findLargestSquare(board):
global answer
a = np.array(board)
for k in reversed(range(a[0].size + 1)):
conv_size = k
for i in range(a[0].size - conv_size + 1):
num = i
for j in range(a[0].size - conv_size + 1):
#print('i:', i, 'j:', j)
print(a[i:i + conv_size, j:j + conv_size])
#print('unique: ',np.unique(a[i:i+ conv_size,j:j+conv_size]).size)
if(np.unique(a[i:i+ conv_size,j:j+conv_size]).size == 1):
#print("returning")
return len(a[i:i+ conv_size,j:j+conv_size])**2
num = num + 1
print("================")
return len(a[i:i+ conv_size,j:j+conv_size])**2
# testBoard = [['x','o','g'],['b','a','j'],['u','q','p']]
testBoard = [['X', 'O', 'O', 'O', 'X'], ['X', 'O', 'O', 'O', 'O'], ['X', 'X', 'O', 'O', 'O'], ['X', 'X', 'O', 'O', 'O'],
['X', 'X', 'X', 'X', 'X']]
print(findLargestSquare(testBoard))
答案 0 :(得分:1)
您可以在O(n^2)
而不是当前O(n^4)
(allsame()
位于O(n^2)
中,并且被称为O(n^2)
次)来执行此操作:
使用新的矩阵best_size,这样best_size[i, j]
应该包含原始棋盘中(i, j)
开始的最大正方形的大小。从此规则结尾处开始填写此矩阵:
def get_best_size(a, best_size, i, j):
# TODO Handle boundaries: best_size = 1 there
if not a[i, j] == a[i+1, j] == a[i, j+1]:
return 1
min_neighbor_best_size = min(best_size[i+1, j], best_size[i, j+1])
if a[i, j] == a[i + min_neighbor_best_size , j + min_neighbor_best_size ]:
return min_neighbor_best_size + 1
else:
return min_neighbor_best_size
只需绘制它就可以告诉您此规则的工作原理。
然后你只需从数组的末尾迭代到开始,并在你处于最佳位置时记住最好的一个:
best = 0
for i in range(ran,-1,-1):
for j in range(ran,-1,-1):
best_size[i, j] = get_best_size(a, best_size, i, j)
best = max(best, best_size[i, j])
return best
答案 1 :(得分:0)
您的代码存在一些根本性的问题,因为它不是您应该如何使用Python。首先尝试阅读一些好的介绍和示例。我推荐这个book和这些scipy lecture notes
让我们从顶部开始
有多种方法可以检查数组是否具有所有相同的元素
numpy有一个返回unique元素的方法。如果所有元素都相同,则此数组的长度应为1
您可以使用第一个元素,使用np.ones
创建一个数组并将其与此元素相乘。初始数组应该等于这个新数组
这种方法究竟应该做什么?
global answer
为什么要全球化?
此行被调用,但您对返回值不执行任何操作。它可能做的只是改变全局答案
这个list
会发生什么。 PS,不要给变量命名built-ins
为什么要使用a = np.matrix(board)
只需将您的电路板保持为numpy.array
,这将是最简单,最有效的。另外,0
和1
的矩阵将比X
和0
如果要在两个方向之一的大小为1时停止算法的递归,1 in a.shape
如果你想在0&n;的numpy.array中找到1上的方块,你可以使用卷积
a = np.zeros((10,10), dtype=int)
ones = ((1, 1), (1, 2), (2, 1), (2, 2), (0, 0), (4, 5))
for point in ones:
a[point] = 1
这使用卷积来搜索原始数组中是否有i i内核
def find_largest_square_helper(a):
for i in range(2, min(a.shape)): # changed this to 2, because the 1 is trivial
kernel = np.ones((i, i), dtype=int)
if scipy.signal.convolve(a, kernel).max() != i**2:
return(i-1)
如果你期望大方块,你可以从最大的方块开始,然后像这样下去:
def find_largest_square_helper2(a):
for i in range(min(a.shape), 0, -1):
kernel = np.ones((i, i), dtype=int)
if scipy.signal.convolve(a, kernel).max() == i**2:
return(i)
如果您不仅在1
数组中查找0
s的最大平方,则循环遍历数组中的所有可能字符,并在集合理解中调用此函数。然后在set
def find_largest_square(board):
a = np.array(board)
max_squares = {find_largest_square_helper(a==char) for char in np.unique(a)}
return max(max_squares)
答案 2 :(得分:0)
<!-- **ImgDashboard.js** -->
Template.ImgDashboard.helpers({
setImageProcessing: function() {
var roomId = localStorage.getItem('roomId');/*set localstorage */
var imageData = ImageData.findOne({RoomId: roomId});
/* ImageData collection in Mongodb */
setTimeout(function(){
var item = "";
imageData.ImageData.forEach(function(data){
var base64String = data.ImageString;
item += '<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3" >\
<div class="center-block" width="300" height="300"
alt="" >\
<img src='+base64String+' class= "img-responsive center-
block"/>\
</div>\</div>'; /* concatenation of images */
}, function(err){
})
$('.image-list').append(item);
},10)
});
<!-- **ImgDashboard.html** -->
<template name="ImgDashboard"> /* template rendered here to display */
{{> Header}}
<div class="container-fluid">
<div> {{setImageProcessing}}</div> /* method from helper */
<div class="image-list">/* images here from helper */
</div>
</div>
</template>
<!-- **Room.html** -->
<div class="container-fluid">
<div class="row">
<div id="carousel-example-generic" class="carousel slide" data-
ride="carousel">
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="images/bedroom-lg.jpeg" class="img-responsive" width="100%" height="597"> /* First block */
</div>
<div class="item">
<img src="images/bedroom-lg.jpeg" class="img-responsive" width="100%" height="597"> /* second block */
</div>
<div class="item">
<img src="images/bedroom-lg.jpeg" class="img-responsive" width="100%" height="597"> /* third block */
</div>
<div class="item">
<img src="images/bedroom-lg.jpeg" class="img-responsive" width="100%" height="597">/* fourth block */
</div>
<div class="item">
<img src="images/bedroom-lg.jpeg" class="img-responsive" width="100%" height="597">/* fifth block */
</div>
</div>
/* -- Controls -- */
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
</div>
import numpy as np
import time
answer = 0
def findLargestSquare(board):
global answer
a = np.array(board)
for k in reversed(range(a[0].size + 1)):
conv_size = k
for i in range(a[0].size - conv_size + 1):
num = i
for j in range(a[0].size - conv_size + 1):
#print('i:', i, 'j:', j)
print(a[i:i + conv_size, j:j + conv_size])
#print('unique: ',np.unique(a[i:i+ conv_size,j:j+conv_size]).size)
if(np.unique(a[i:i+ conv_size,j:j+conv_size]).size == 1):
#print("returning")
return len(a[i:i+ conv_size,j:j+conv_size])**2
num = num + 1
print("================")
return len(a[i:i+ conv_size,j:j+conv_size])**2
是不必要的,无处可用。当然不需要在算法中使用answer
global
和conv_size = k
是不必要的。如果你想这样命名,那么在for循环中这样做,num = i
甚至不用于算法的其余部分
num
每次创建一个新数组(或range(a[0].size)
,我不是100%肯定),如果view
更短,则会产生问题。 a[1]
更清洁
代替循环两次,您可以使用max_size = min(a.shape)
生成子方格边缘的坐标
itertools.product
返回一个生成器,其结果为5:
[(0,0),(0,1),(0,2),(0,3),(0,4),(1,0),(1,1),(1,2) ),(1,3),(1,4),(2,0),(2,1),(2,2),(2,3),(2,4),(3,0), (3,1),(3,2),(3,3),(3,4),(4,0),(4,1),(4,2),(4,3),(4) ,4)]
for size in reversed(range(2, max_size + 1)):
k = max_size = size + 1
for i, j in itertools.product(range(k), repeat=2):
如果没有if(np.unique(a[i:i+ conv_size,j:j+conv_size]).size == 1):
#print("returning")
return len(a[i:i+ conv_size,j:j+conv_size])**2
或array
的双重创建,可以更干净
view
sub_square = a[i:i+size, j:j+size]
if len(np.unique(sub_square)) == 1:
return len(sub_square) ** 2
# calculations
答案 3 :(得分:0)
我确定了第一个答案:
def get_best_size(a, best_size, i, j, x):
if i+1 >= a.shape[0] or j+1 >= a.shape[1]:
return 1
if not (a[i, j] == a[i+1, j] == a[i, j+1] == x):
return 1
min_neighbor_best_size = int(min(best_size[i+1, j], best_size[i, j+1]))
if a[i, j] == a[i + min_neighbor_best_size , j + min_neighbor_best_size ]:
return min_neighbor_best_size + 1
else:
return min_neighbor_best_size
# looking for largest X block in A
def doGetBest(a, x):
best_size = np.ones(a.shape)
best = 1
best_pair = (0,0)
for i in range(a.shape[0]-1,-1,-1):
for j in range(a.shape[1]-1,-1,-1):
best_size[i, j] = get_best_size(a, best_size, i, j, x)
if best < best_size[i, j]:
best = best_size[i, j]
best_pair = (i,j)
return best, best_pair
答案 4 :(得分:0)
由于没有人提供DP方法示例,因此它是:
def findLargestSquare(M):
n = len(M)
S = [[0 for _ in range(n)] for _ in range(n)]
max_s = 0
for i in range(1, n):
for j in range(1, n):
if M[i][j] == 1:
S[i][j] = min(S[i][j-1], S[i-1][j], S[i-1][j-1]) + 1
if S[i][j] > max_s:
max_s = S[i][j]
return max_s
作为比较,这是我在求职面试中想到的一种蛮力方法(对于500x500矩阵,它要慢100倍):
def findLargestSquare(arr):
if sum([sum(row) for row in arr]) == 0:
return 0
n = len(arr)
for k in range(n, 1, -1): #check every kxk square from k=n to k=2
for i in range(n-k+1):
#for every row i check every starting position j from j=0 to j=n-k
j_next = 0
for j in range(n-k+1):
if j > j_next:
#break as soon as an element of this row segment is not 1:
count = 0
for p in range(j, j+k, 1):
if arr[i][p] != 1:
j_next = p
break
else: ##check the rows below:
keep_going = True
for r in range(i+1, i+k, 1):
if keep_going:
for p in range(j, j+k, 1):
if arr[r][p] != 1:
keep_going = False
j_next = p
break
else:
count += 1
if count == k-1: #square is found
return k
else:
return 1