查詢----二維陣列的查詢之楊氏矩陣
演算法研討的論文【原創分享】
楊氏矩陣 Young Tableau
前幾天演算法課上老師提到了一個數據結構--Young Tableau,只是簡單的提了一下,沒有仔細的講解,於是自己在網上搜集了一些資料,並且加以研究,感覺楊氏矩陣(Young Tableau)是一個很奇妙的資料結構,他類似於堆的結構,又類似於BST的結構,對於查詢某些元素,它優於堆;對於插入、刪除它比BST更方便。
首先介紹一下這個資料結構的定義,Young Tableau有一個m*n的矩陣,讓後有一陣列 a[k], 其中 k<=m*n ,然後把a[k]中的數填入 m*n 的矩陣中,填充規則為(如圖1-1):
1. 每一行每一列都嚴格單調遞增
2. 如果將a[k]中的數填完後,矩陣中仍有空間,則填入 ∞。
1 |
2 |
3 |
4 |
5 |
6 |
|
1 |
3 |
5 |
7 |
8 |
11 |
a |
4 |
6 |
9 |
14 |
15 |
19 |
b |
10 |
21 |
23 |
33 |
56 |
57 |
c |
34 |
37 |
45 |
55 |
∞ |
∞ |
d |
∞ |
∞ |
∞ |
∞ |
∞ |
∞ |
e |
圖1-1
則現在討論,這個資料結構的幾種操作,而在這些操作中,我們會發現堆排序的影子,並且這些操作具有很好的時間複雜度。
條件:一個已經建好的楊氏矩陣(Young Tableau
操作:
【1】 在楊氏矩陣中插入元素x ---- Insert(x)
【2】 在楊氏矩陣中刪除位於 (x, y) 位置的元素---- Delete(x, y)
【3】 返回x是否在矩陣中----Find(x)
其中1-2操作類似於堆的操作,而4操作類似於BST的操作。下面我就用我
自己的理解把這幾個操作加以解釋。
【1】 插入操作
本操作的時間複雜度為O( n + m ),其操作類似於堆排序的SIFT-UP演算法(具體演算法見《演算法設計技巧與分析》 M.H,Alsuwaiyel 著)。它的堆的結構在這裡表現為某個元素Y[x, y] 下面和右面的兩個元素 Y[x, y+1] ,Y[x+1, y]均比Y[x, y]要大。於是其插入演算法可以描述為,首先把待插入元素以行為主序置於所有有效數字(除了無窮以外的數)最後面,如將x=2,放入 圖1-1 的d5的位置,然後執行類似於SIFT-UP的操作,將x與它左邊(記為x-l)及上面(記為x-u)的數進行比較,根據比較結果有三種可能的操作:
1:x-u > x 且x-u >= x-l 則將x 與 x-u進行交換
2:x-l > x 且x-l > x-u 則將x 與 x-l進行交換
3: x >= x-l 且 x > x-u 則x 不動,此時已經插入成功
(可以有其他合理的約定)
對例子插入2進行操作如圖1-2箭頭的操作方向。
1 |
2 |
3 |
4 |
5 |
6 |
|
1 |
3 |
5 |
7 |
8 |
11 |
a |
2 |
6 |
9 |
14 |
15 |
19 |
b |
4 |
10 |
21 |
23 |
33 |
57 |
c |
34 |
37 |
45 |
55 |
56 |
∞ |
d |
∞ |
∞ |
∞ |
∞ |
∞ |
∞ |
e |
圖1-2
由上述的操作知其時間複雜度最大為行列之和,即O(m+n)。
【2】 刪除操作
操作類似於插入操作,其時間複雜度也為O(m+n)。其操作類似於堆排序的SIFT-DOWN演算法。刪除演算法可以描述為,首先將刪除的位置(x, y)的數字刪除,然後調整,把楊氏矩陣中的最大值k(可以行為主序進行搜尋到最後)填入到被刪除位置,然後讓此數與其下面的數(k-d)和右面的數進行(k-r)比較,此時比較結果為兩種,因為此時元素一定會下移:
1:k-d > k-r 將k-r 和 k進行交換
2:k-d < k-r 將k-d 和 k進行交換
舉例 刪除圖1-1的a3位置的元素5如圖1-3
1 |
2 |
3 |
4 |
5 |
6 |
|
1 |
3 |
7 |
8 |
11 |
19 |
a |
4 |
6 |
9 |
14 |
15 |
57 |
b |
10 |
21 |
23 |
33 |
56 |
∞ |
c |
34 |
37 |
45 |
55 |
∞ |
∞ |
d |
∞ |
∞ |
∞ |
∞ |
∞ |
∞ |
e |
圖1-3
由操作知,刪除演算法時間複雜同樣最多為行列之和,即O(m + n)。
【3】查詢演算法
查詢演算法類似於BST二叉排序樹,不過需要在其思想上稍微進行修改,才能滿足楊氏矩陣的查詢操作,同樣利用楊氏矩陣的性質,不過此時應該換一個角度思考問題,因為與BST二叉排序樹類比,所以應該從左下角開始看起(如 圖1-1d1位置),該元素的上面的元素比本身小和右面的元素比本身大,這樣就與BST二叉排序樹具有相同的性質。所以在查詢時從左下角不斷的比較,從而最終確定所查詢元素位置。
如查詢19,比較順序如圖1-4
1 |
2 |
3 |
4 |
5 |
6 |
|
1 |
3 |
5 |
7 |
8 |
11 |
a |
4 |
6 |
9 |
14 |
15 |
19 |
b |
10 |
21 |
23 |
33 |
56 |
57 |
c |
34 |
37 |
45 |
55 |
∞ |
∞ |
d |
∞ |
∞ |
∞ |
∞ |
∞ |
∞ |
e |
圖1-4
此演算法的時間複雜度同前兩個演算法,複雜度也是O(m + n)。
總結:
經過這次對楊氏矩陣的研究,感覺書本上學到的資料結構只是一些最基本的東西,其實在生活中有很多複雜,並且有趣的資料結構模型,但是這些資料結構模型最終將可以用已有的簡單資料結構來經過變換,以及組合來構成,同時相應的演算法也就有所擴充套件。所以我認為在學習的過程中應該注重對一些問題的深入研究。
相關推薦
查詢----二維陣列的查詢之楊氏矩陣
演算法研討的論文【原創分享】 楊氏矩陣 Young Tableau 前幾天演算法課上老師提到了一個數據結構--Young Tableau,只是簡單的提了一下,沒有仔細的講解,於是自己在網上搜集了一些資料,並且加以研究,感覺楊氏矩陣(Young Tableau)是一個很奇妙
牛客66題(1)二維陣列查詢
在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。 class Solution { public: bool Find(int target,
劍指offer[二維陣列查詢]
劍指offer[二維陣列查詢] 題目描述 思路 程式碼 細節知識 題目描述 在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成
3--查詢二維陣列包含的數字
/** * 在一個二維陣列中,每一行都按照從左往右遞增的順序排列,每一列都按照從上到下遞增的順序排列。 * 請完成一個函式,輸入這樣的一個二維陣列和整數,判斷陣列中是否存在該整數 * * 可從左下角(向上遞減向右遞增)或右上角(向下遞增向左遞減)開始
【劍指offer{1-3}】二維陣列查詢、空格替換、從尾到頭列印連結串列
注:程式碼均在牛客網上執行,結果均通過! 二維陣列查詢 題目描述 在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函
行列都有序的二維陣列查詢問題
在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。 #include <iostream> #include <vector&g
java 基礎資料遍歷(2)----二維陣列查詢
題目要求: 一個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。 輸入描述: array: 待查詢的二維陣列 target:查詢的數字 輸
Search a 2D Matrix:二分查詢二維陣列
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the fol
Linq中查詢二維陣列
以下程式碼為在一個4*4的二維int陣列中將大於5的元素查出:staticvoid Main(string[] args) {int[,] array = newint[4, 4];for (int i = 0; i < 4; i++)for (int j
二維陣列查詢問題
題目:在一個二維陣列中,每行都按照從左至右遞增的順序排序,每一列都按照從上到下遞增順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有這個整數。 最容易想到就是逐個遍歷矩陣,但是沒有用到題幹每一列和每一行都遞增的資訊。通過觀察,從矩陣
Java 查詢二維陣列中是否含有某個數
在二維陣列中,每一行都按照從左到右遞增的順序排序, 每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。 public class fin
二維陣列模型之指標陣列
#include <stdio.h> #include <stdlib.h> #include <string.h> #if 0 int main(int agrc, char *argv[]) { int i = 0; for(; i<
實驗7-二維陣列的運用 楊輝三角
楊輝三角 Time Limit: 1000MS Memory Limit: 65536KB Problem Description 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 上
Typescript | 二維陣列(泛型)矩陣行列互換
/* * @Author: Prpr_Saber * @Date: 2018-11-02 17:06:29 * @Last Modified by: Prpr_Saber * @Last Modified time: 2018-11-02 21:41:47 */ export let t
//楊氏矩陣 有一個二維陣列. 陣列的每行從左到右是遞增的,每列從上到下是遞增的. 在這樣的陣列中查詢一個數字是否存在。
//楊氏矩陣 有一個二維陣列. 陣列的每行從左到右是遞增的,每列從上到下是遞增的. 在這樣的陣列中查詢一個數字是否存在。 時間複雜度小於O(N); 我用一個while迴圈實現了該要求 #include <stdio.h> #include <windows.h>
//楊氏矩陣 有一個二維陣列. 陣列的每行從左到右是遞增的,每列從上到下是遞增的. 在這樣的陣列中查詢一個數字是否存在
題目: //楊氏矩陣 有一個二維陣列. 陣列的每行從左到右是遞增的,每列從上到下是遞增的. 在這樣的陣列中查詢一個數字是否存在。 時間複雜度小於O(N); 陣列: 1 2 3 2 3 4
楊氏矩陣 //有一個二維陣列. //陣列的每行從左到右是遞增的,每列從上到下是遞增的. //在這樣的陣列中查詢一個數字是否存在。 //時間複雜度小於O(N);
//陣列: //1 2 3 //2 3 4 //3 4 5 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdlib.h> #include <stdio.h> int search(int a
前端常見演算法面試題之 - 二維陣列中的查詢[JavaScript解法]
前端常見演算法面試題之 - 二維陣列中的查詢[JavaScript解法] 題目描述 輸入輸出分析 實現思路 程式碼實現 題目描述 在一個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個
劍指offer刷題之二維陣列中的查詢
在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數 class Solution: # array 二維列表  
劍指offer(一)之二維陣列中的查詢
題目描述 在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。 思路: 思路來源討論。。。 由於從上至下遞增,從左至右遞增 假定當前位置