Young tableaus 楊氏矩陣 的分析

2021-08-19 16:17:58 字數 2460 閱讀 2657

楊氏矩陣是在很多面試和討論中用到比較多的乙個話題。它本身獨特的構造使得它的一些增刪查改的操作和堆排序以及二分搜尋的思想很類似。它本身問題不難,實際操作的時候會稍微有點繁瑣。

假定我們有乙個mxn的矩陣,它的每一行以及每一列都是排好序的。我們可以稱這個矩陣為young tableaus(楊氏矩陣)。在這個矩陣裡,可以有某些元素不存在的情況,也就是說,這些位置的值被設定為無窮大(∞)。我們以元素按照非遞減的順序為例,假設我們有這麼一組數字,我們可以構造乙個如下的楊氏矩陣:

由前面的基本定義,我們發現幾個很直觀的特性:

一、對於每個元素,如果不是值為∞的,它的右邊和下面的元素都大於或者等於它。那麼,對於整個矩陣來說,它最小的元素肯定在最左上角,也就是元素a[0][0]。

二、由於整個矩陣可以有空缺的元素,我們用∞來表示。那麼,如果它最右下角的元素a[m][n]不是∞的話,我們可以推斷這個矩陣是滿的矩陣,也就是說不存在∞的元素。

ok,有了前面的這部分定義,我們來看看矩陣的幾個常見操作吧。

insert元素的過程就是我要新增加乙個元素到矩陣中,保證我插入的這個元素最後要放在乙個適當的位置以滿足楊氏矩陣的特性。這裡最關鍵的就是有兩個點:1. 找到乙個初始插入的點。 2. 調整,將元素放到合適的位置上。

放元素的話,我們可以考慮到,只要這個矩陣不是滿的,那麼他最後的那個放置元素的點應該是最右下角的那個。我們可以考慮先把元素放到這個點。然後再來調整。以前面給出的矩陣為例,假設我們要插入乙個元素7,我們插入元素後的矩陣結果如下:

調整的話,我們考慮,假設它左邊的元素和上面的元素都存在,而且比自己大的話,我們就需要取中間最大的那個元素,和當前元素交換位置。對於兩邊元素一樣大的情況,先比較同行的或者同列的都可以。假定我們先比較同一列的,然後比較同一行的,則位置調整的步驟如下:

1. 7 和上面的∞比較,因為7小於∞,根據先和同列元素比較的方式,則先將7與它上面的元素交換。這樣一直將7交換到了最右上角。如下圖:

2. 現在,我們再來比較。7已經到了最右上角,它往上沒有元素了,往左有乙個9。所以在往左或者往上的方向上比它大的最大元素為9。它需要和9交換。如下圖:

這個方法的時間複雜度為o(m+n)。我們在實現中還要考慮的乙個點就是,既然我們用∞來表示空缺的元素,在實際實現中該用什麼值呢?很多版本的實現用乙個特殊的數值。這裡假定所有值都在int範圍,用integer.max_value來表示這個∞的特殊值。

刪除乙個元素的過程也可以類似的考慮如下。假定我們要把矩陣中指定的乙個元素去掉,那麼,我們就需要將它右邊或者下面的元素進行調整,來填補原來的位置以保證後續的矩陣符合楊氏矩陣的特性。那麼這裡就有這麼一種思路:

1. 將要刪除的元素設定為∞。

2. 再通過將∞的這個元素向友和向下調整,最終移到矩陣滿足條件為止。

以下圖為例,假設我們刪除a[0][0]這個點的元素。

在將a[0][0]刪除後我們要比較它右邊和下面的元素,如果哪個小就交換它和這個最小元素的位置。在這個問題中,a[0][1]為4,a[1][0]為3.所以交換a[0][0]和a[1][0]的位置,如下圖:

根據前面的推導,先後交換的元素為5, 12.最終得到如下圖的結果:

如果我們還記得heapsort裡面的heapify,會覺得他們的思想簡直是太像了。沒錯,這就相當於乙個heapify的過程。我們進行youngify的時間複雜度為o(m+n)。

查詢元素有幾種辦法。乙個比較直接的辦法就是逐行逐列的去查詢,找到之後就返回。這種方法的時間複雜度為o(mxn)。

還有一種就是利用了矩陣的乙個性質,他的每行每列都是排序的。那麼我們可以用二分查詢的辦法來做。這樣查詢的話就需要逐行的去查,時間複雜度大致為o(mlogn)。在這裡,前面兩種辦法就不再詳細實現了。

我們來考慮第三種方法。我們的矩陣小的元素在左上方向,大的元素在右下方向。如果我們考慮矩陣的左下角或者右上角的話,會發現乙個有意思的事情。就是他們的乙個方向的元素大於等於自己而另外乙個方向的元素小於等於自己。假定我們從右上角開始來查詢,目的元素比當前元素大則向下查,比當前元素小則向左查。這樣最終可以找到元素或者遍歷到元素的對角位置。以下圖為例,假設我們要找元素5,則起始點是在元素9,比較發現5小於9,則找9左邊的元素。

我們再依次比較下去,5<7,則比較7左邊的元素4,5>4,則再比較4下面的元素8,這樣依次下去,形成乙個如下圖的比較過程:

很顯然,有了這麼一番分析,我們查詢的**也就出來了:

這裡也可以返回找到元素的座標。為了偷個懶就直接用有沒有查到來作為結果了。 我們也可以很明顯的看到,find方法的時間複雜度為o(m+n)。

modify的過程基於前面的討論其實已經很明了了。我們看,如果我們修改的值比當前值大,就相當於乙個youngify的過程,進行調整就可以了。如果修改的值比當前的值小,則利用insert裡面的decreasekey方法,向左上角調整。

總而言之,言而總之,這個過程該怎麼做,***。

關於楊氏矩陣本身的問題不多,很多都是通過它的一些應用來討論。比如說乙個這樣的矩陣裡,有正整數和負整數,那麼有多少個正整數呢?這一類的問題挺多的,無非是一些常用特性的變體。大家可以私底下去考慮考慮。

introduction to algorithms

楊氏矩陣查詢

題目為 在乙個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成乙個函式,輸入這樣的乙個二維陣列和乙個整數,判斷陣列中是否含有該整數。例如下面的二維陣列就是每行 每列都遞增排序,如果在這個陣列中查詢數字6,則返回true 如果查詢數字10,由於陣列不含有該數字...

楊氏矩陣查詢

方案一 時間複雜度o m n 原理 從右上角開始 左下角相同 如果arr i j t,就向左查詢,如果arr i j 2013.7.23 0423 function 楊氏矩陣查詢 在乙個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成乙個函式,輸入這樣的乙個...

楊氏矩陣查詢

題目描述 楊氏矩陣,即在乙個二維陣列中,每一行都按照從左到右嚴格遞增的順序排序,每一列都按照從上到下嚴格遞增的順序排序。請完成乙個函式,輸入這樣的乙個 n n的二維陣列和 m個整數,判斷陣列中是否含有上述 m個整數。你能解決這個問題嗎?輸入格式 可能有多個測試輸入,第一行給出總共的測試輸入的個數。對...