2017-01-28 223 views
2

我被困在一個簡單的問題,我正在尋找比我更好的解決方案。矩陣陣列的最大部分

我有一個整數矩陣陣列(標籤[N] [M])和整數(ķ),我必須找到具有它總和的最小矩形(子矩陣陣列)的元素大於ķ

所以,我的當前的解決方案的嘗試是:

  1. 使附加矩陣陣列(總和[N] [M])和整數溶液 =無窮
  2. 對於每個1 < < = Ñ + 1和1 < Ĵ < = 中號 + 1

    sum[ i ][ j ] = sum[ i - 1 ][ j ] + sum [ i ][ j - 1] + tab[ i ] [ j ] - sum[ i - 1] [ j - 1] 
    
  3. 然後看看上開始於每個矩形FE矩形( x,y)和末端(a,b)

    Rectangle_(x,y)_(a,b) = sum[ a ][ b ] - sum[ a - x ] [ b ] - sum[ a ][ b - y ] + sum[ a - x ][ b - y ] 
    

    如果Rectang le_(X,Y)_(A,B)> = K然後溶液= current_solution的最小和(a - x)的*(B - Y)

但是這種解決方案是相當慢(四次時間),有沒有可能讓它更快?我正在尋找迭代對數時間(或更糟糕/更好)。我設法減少了我的時間,但不是很大。

+1

矩陣是否可以包含負值? (我知道你說的整數,但只是檢查) – samgak

+0

哦...對了,我忘了提及它,只有intigers> = 0 –

回答

0

如果矩陣只包含大於等於0的值,那麼在1D情況下有一個線性時間解,可以在2D情況下將其擴展爲立方時間解。

對於1D的情況,您可以從左到右進行一次遍歷,在整個數組上滑動一個窗口,隨着時間的推移或縮小,使得間隔中包含的數字總是至少爲k如果這是不可能的,則退出循環)。

最初,設置結合的間隔與所述第一元件的左手食指,並結合至-1正確的索引,則在一個循環:

  • 遞增1結合的右側,然後不斷遞增直到達到區間內的值總和爲> k或數組的末尾。
  • 遞增左邊界以儘可能小地縮小間隔,而不讓數值總和小於或等於k。
  • 如果結果是一個有效的時間間隔(意思是第一步沒有找到一個有效的時間間隔到達數組的末尾),那麼比較它到目前爲止的最小值並在必要時進行更新。

如果允許負值,這不起作用,因爲在第二步中,您需要能夠假設收縮間隔總是導致較小的總和,所以當總和低於k時,您知道這是給定間隔端點的最小可能值。

對於2D情況,您可以遍歷所有可能的子矩陣高度,以及遍歷給定高度的每個可能的起始行,並對每行執行此水平掃描。

在僞碼:

假設有一個功能rectangle_sum(x, y, a, b),從(X,Y)返回值的總和到(A,B),其中包括與運行在O(1)時所使用的求和麪積表。

for(height = 1; height <= M; height++) // iterate over submatrix heights 
{ 
    for(row = 0; row <= (M-h); row++) // iterate over all rows 
    { 
     start = 0; end = -1; // initialize interval 
     while(end < N) // iterate across the row 
     { 
      valid_interval = false; 
      // increment end until the interval sums to > k: 
      while(end < (N-1)) 
      { 
       end = end + 1; 
       if(rectangle_sum(start, row, end, row + height) > k) 
       { 
        valid_interval = true; 
        break; 
       } 
      } 
      if(!valid_interval) 
       break; 
      // shrink interval by incrementing start: 
      while((start < end) && 
       rectangle_sum(start+1, row, end, row + height) > k)) 
       start = start + 1; 

      compare (start, row), (end, row + height) with current smallest 
      submatrix and make it the new current if it is smaller 
     } 
    } 
} 
0

我已經看到了矩陣矩形問題的一些答案,這些問題通過解決類似的一維問題,然後將其應用到矩陣的每一行,每一行通過取兩個相鄰行的總和形成來自三個相鄰行的總和,等等。所以這裏試圖找到一個至少有一個給定總和的最小間隔。 (很顯然,如果你的矩陣高而瘦,而不是短而胖,你可以使用列而不是行)

從左到右工作,保持到目前爲止所看到的值的所有前綴的總和,直到當前位置。以位置結尾的間隔的值是該位置的總和(包括該位置),減去在間隔開始之前結束的前綴的總和。因此,如果您將前綴總和的列表保留在當前位置之前,那麼您可以在每個點處找到通過閾值的最短時間間隔。我將在下一段中解釋如何有效地搜索這些內容。

實際上,您可能不需要所有前綴總和的列表。較小的前綴總和更有價值,並且結尾的前綴總和更有價值。因此,在另一個前綴和之前結束並且也大於該另一個前綴和的任何前綴和是沒有意義的。因此,您想要的前綴總和可以排列成一個列表,保留它們的計算順序,但也具有每個前綴總和小於其右側的前綴總和的屬性。這意味着,當您想要查找最多隻有給定值的最接近的前綴和時,您可以通過二分搜索來完成此操作。這也意味着,當你計算一個新的前綴總和時,你可以把它放在列表中的位置,只需放棄列表右端的大於或等於它的所有前綴總和即可。

+0

謝謝anwser,這真的很有用:) –