日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构与算法--数组:二维数组中查找

發(fā)布時間:2023/12/4 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法--数组:二维数组中查找 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

數(shù)組

  • 數(shù)組最簡單的是數(shù)據(jù)結(jié)構(gòu),占據(jù)一整塊連續(xù)的內(nèi)存并按照順序存儲數(shù)據(jù),創(chuàng)建數(shù)組時候,我們需要首先指定數(shù)組的容量大小,然后根據(jù)大小分配內(nèi)存。即使我們只在數(shù)組中存儲一個元素,亞需要為所有數(shù)據(jù)預(yù)先分配內(nèi)存,因此空間使用效率差,經(jīng)常會有空閑區(qū)域沒有得到充分利用。
  • 由于數(shù)組中內(nèi)存是連續(xù)的,于是可以根據(jù)下標(biāo)在O(1)時間內(nèi)讀/寫任何元素,因此時間效率很高。
  • 為解決數(shù)組空間效率問題,人們設(shè)計實現(xiàn)了多種動態(tài)數(shù)組,Java中的vector。為了避免浪,我們先為數(shù)組開辟一個較小的空間,然后向數(shù)組添加元素的過程中,當(dāng)元素個數(shù)超過數(shù)組容量的時候,我們會重新分配一個更大的空間,接著吧之前的數(shù)據(jù)復(fù)制到新的駐足中,在將之前的內(nèi)存釋放,這樣就能減少內(nèi)存的浪費(fèi)。但是每一層擴(kuò)充數(shù)組容量都有大量的額外操作,這多時間性能有負(fù)面的影響,因此使用動態(tài)數(shù)組時候要盡量減少改變數(shù)組容量大小的次數(shù)。

算法題:二維數(shù)組中查找

  • 題目:在一個二維數(shù)組中,每一行從左到右遞增順序存儲,每一列都按照從上到下遞增順序排序。完成一個函數(shù),輸入這樣一個二維數(shù)組和一個整數(shù),輸出數(shù)組中是否包含改整數(shù)以及改整數(shù)的位置。
  • 分析過程如下: 例如下面二維數(shù)組,每行,列都遞增。如果這個數(shù)組中查找數(shù)字6,則返回true,位置(2,1)。如果查找數(shù)字5返回false

1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20

錯誤解法分析過程如下
  • 按照題目要求,每列,行都遞增,如上,通過觀察以上矩陣的特性,很多同學(xué)會采用二分法,步驟如下:
    • 將二維數(shù)組看成是一個現(xiàn)象的結(jié)構(gòu),總共有20個元素,left=0,right=20, mid= (left+right)/2=10
    • 取中間位置元素值value與目標(biāo)元素key比較
    • value == key 則得出結(jié)果
    • value < key則left = mid + 1
    • value > key 則right = mid - 1
    • 具體實現(xiàn)如下
/*** 錯誤案例* @author liaojiamin* @Date:Created in 13:59 2020/10/30*/ public class FindOne {public static Integer[][] getTwoDimenArray(int rows, int cloumns){Integer[][] twoDimen = new Integer[rows][cloumns];for (int i = 0; i < rows; i++) {for (int j = 0; j < cloumns; j++) {Integer key = (i+1) * (j+1);twoDimen[i][j] = key;System.out.print(key + " ");}System.out.println("");}return twoDimen;}public static void findOneInTwoDimenArray1(int rows, int cloumns, Integer key){if(rows <=0 || cloumns <=0){return;}Integer[][] twoDimen = getTwoDimenArray(rows, cloumns);if(twoDimen == null){return;}boolean isInArray = false;int keyCloumns = -1;int keyRows = -1;int left = 0;int right = rows * cloumns -1;int col = cloumns;while (left <= right){int mid = (left + right) / 2;Integer value = twoDimen[mid/ col][mid%col];//中間位置if(value == key){keyRows = mid/col;keyCloumns = mid%col;isInArray = true;break;}else if(value < key){left = mid + 1;}else {right = mid - 1;}}System.out.println("isInArray: "+ isInArray + " position: rows:" +keyRows + " cloums:" + keyCloumns);}public static void main(String[] args) {findOneInTwoDimenArray1(4, 5, 8);} }
  • 以下測試案例:
//測試一:正確 inPut:4,5,8 outPut: 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 isInArray: true position: rows:1 cloums:3 //測試二:錯誤 input:5,4,8 1 2 3 4 2 4 6 8 3 6 9 12 4 8 12 16 5 10 15 20 isInArray: false position: rows:-1 cloums:-1
  • 如上測試用例可知,以上解法是錯誤的,原因在于雖然此二維數(shù)組每一列每一行都遞增,當(dāng)并不代表中間元素mid之前的元素一定小于mid導(dǎo)致程序出錯。
正確解法分析過程如下
  • 還是將二維數(shù)組看成矩陣,,從中選一個元素 m與目標(biāo)值key比較,分三種情況分析查找,

    • 情況一 當(dāng) m == key,結(jié)束查找
    • 情況二 當(dāng) m < key,根據(jù)數(shù)組排序規(guī)則,要查找的數(shù)字應(yīng)該在當(dāng)前選區(qū)的位置的右邊或者下面
    • 情況三 當(dāng)m > key,同樣的,要查的數(shù)字應(yīng)該在左邊或者上面

  • 如上分析,由于需要朝招的數(shù)字相對當(dāng)前選取的m的位置有可能兩個區(qū)域,而且有重疊,這樣看起來就復(fù)雜了。

  • 我們將問題具體化,。下面以上圖中矩陣中查找數(shù)字7 為案例,一步步分析查找過程。

  • 之前之所以困難,是我們在二維數(shù)組的中間選取的數(shù)字m 與目標(biāo)值key比較,這樣導(dǎo)致下一次需要查找的兩個相互重疊的區(qū)域。如果我們從數(shù)組的一個角上選取,情況如下:

    • 首先選右上角數(shù)字9, 9 > 7,并且9 還在第四列的第一個數(shù)字,所有,7 不可能在第四列

    • 將剩下三列看成一個新的二維數(shù)組,同樣選右上角 8 > 7 ,同樣可以排除第三列數(shù)

    • 將剩下兩列看成一個新二維數(shù)組,同樣選右上角2 < 7,那么要查找的7 可能在2的右邊也可能在2 的下面,因為之前的操作已經(jīng)將右邊的所有數(shù)據(jù)都排除了,所有必定在2 的下面,并且將2 這一行踢出,只剩下3*2 的二維數(shù)組,如下

    • 剩下上圖中,同樣用這個方法,去右上角4 < 7 ,所以不再這一行,可能在4下面,剩下2*2 的二維數(shù)組

  • 接著在取右上角 7 = 7 得出最終答案。

總結(jié)
  • 以上查找過程,有如下規(guī)律:首先選取數(shù)組中右上角元素,
    • 如果改數(shù)字等于要查找數(shù)字,結(jié)束查找
    • 如果改數(shù)字小于要查找數(shù)字,踢出這個數(shù)字所在行
    • 如果這個數(shù)字大于要查找的數(shù)字,踢出這個數(shù)字所在的列
    • 依次每一步都在查找范圍內(nèi)踢出一列或者一行,逐步縮小范圍。直到查詢到或者為空。
    • 如下代碼實現(xiàn)。
    • 時間復(fù)雜度 O(max(rows, cloumns)),空間復(fù)雜度 O(1)
/*** * @author liaojiamin* @Date:Created in 13:59 2020/10/30*/ public class FindOne {public static Integer[][] getTwoDimenArray(int rows, int cloumns){Integer[][] twoDimen = new Integer[rows][cloumns];for (int i = 0; i < rows; i++) {for (int j = 0; j < cloumns; j++) {Integer key = (i+1) * (j+1);twoDimen[i][j] = key;System.out.print(key + " ");}System.out.println("");}return twoDimen;}public static void findOneInTwoDimenArray2(int rows, int cloumns, Integer key){if(rows <=0 || cloumns <=0 || key == null){return;}Integer[][] twoDimen = getTwoDimenArray(rows, cloumns);if(twoDimen == null){return;}boolean isInArray = false;int keyCloumns = cloumns -1;int keyRows =0;while (keyCloumns >= 0 && keyRows < rows){if(twoDimen[keyRows][keyCloumns] == key){System.out.println("isInArray: "+ isInArray + " position: rows:" +keyRows + " cloums:" + keyCloumns);break;}else if(twoDimen[keyRows][keyCloumns] > key){keyCloumns --;}else {keyRows ++;}}}public static void main(String[] args) {findOneInTwoDimenArray2(5, 4, 8);} }
  • 測試用例:
    • 二維數(shù)組中查找包含的數(shù)字,數(shù)組中最大值,最小值,介于最大最小之間的值
    • 二維數(shù)組中查找不包含的數(shù)字,大于最大值,小于最小值,介于最大最小之前的不存在的值
    • 特殊輸入 null
其他思路
  • 以上是去右上角的數(shù)字,統(tǒng)一,可以選左下角的數(shù)字,
  • 不能選左上角的數(shù)字,例如選擇1, 1 < 7 ,那么7 位于1 的下面或者右邊,沒有參考意義。
  • 不能選右下角的數(shù)字,例如15 , 15 > 7,那么7 位于15 的上面或者左邊,沒有參考意義。

上一篇 數(shù)據(jù)結(jié)構(gòu)與算法–實現(xiàn)Singleton模式
下一篇:數(shù)據(jù)結(jié)構(gòu)與算法–字符串:字符串替換

總結(jié)

以上是生活随笔為你收集整理的数据结构与算法--数组:二维数组中查找的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。