1. 程式人生 > >劍指offer(1):數組

劍指offer(1):數組

abs views 二維數組 如同 pad enter 數組與指針 在線 c語言細節

1 寫作計劃

最近在看《劍指offer》,發現自己有很多的數據結構與算法的基礎知識要復習,《好書一起讀(131):讓寫作更好》中提到用寫作倒逼閱讀,我很是贊同。所以,計劃以《劍指offer》為中心,以記錄復習心得目的,寫一系列數據結構與算法的文章。

  • 文章結構
    文章從概念介紹切入,接著介紹相關的語言細節(以C語言和Python為主),最後以《劍指offer》中的編程題做結。

2 什麽是數組

一提到數組,我第一時間經典的C語言實現和與之對應的一片定長連續的內存空間。數組的讀寫操作很快,時間復雜度為o(1),但是因其必須事先指定長度,所以空間利用率不高。數組的下標是數組中元素的標識,可以當做元素的身份證使用,在需要記錄大量數據時,要利用好數組下標。

3 C語言細節

該節分3個部分介紹C語言從數組的必要語言細節。

3.1 數組越界問題

C語言不強制檢查數組下標是否越界,使用時應時刻註意越界問題。

這個是一個毫無意義的問題,因為C語言根本不允許數組越界。
數組越界是一種Undefined behavior,C語言沒規定程序運行結果,編譯器也不保證這個結果。C語言規定這種錯誤編譯器不必指出,所以編譯可能會正常通過,但這依然是一種錯誤,且責任在CODER。
因此這是一個毫無意義的問題,就如同問襪子燉茄子會是什麽味道。只有傻逼才會用襪子燉茄子然後親自嘗嘗——這就是那個“解答”的本質。

作者:薛非
鏈接:https://www.zhihu.com/question/22897368/answer/22999166
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。

3.2 數組與指針

本節介紹數組與指針之間的關系以及數組在使用中的註意點。

數組名是特殊的指針

本節介紹數組與指針的共同點和不同點。
以數組int a[10];為例:

  1. int a[10];
  2. int n = 10;
  3. int a[n]; //定義數組時,長度不可以為變量,該語句非法

共同點:通過指針訪問數組元素

  • a[i]*(a+i)&a[i]a+i都是等價的。
  • 通過等價指針訪問數組
  1. int *pa;
  2. pa = &a[0]; //指針pa指向數組的0元素地址
  3. pa = a; //這個寫法和上句等價
  4. x = *(pa+1);
  5. x = a[1];
    //這兩句賦值語句等價

不同點:數組名與指針的區別

指針是一個變量,但是數組名不是變量。

  1. int *pa;
  2. pa = &a[0]; //指針pa是可以被賦值的,其指向地址可以改變
  3. int b[10];
  4. a = b; //a不可以被賦值,該語句非法

函數中傳遞的數組是指針(地址)

  • 以《劍指offer》中的代碼為例:
  1. int GetSize(int data[])
  2. {
  3. return sizeof(data);
  4. }
  5. int main()
  6. {
  7. int data1[] ={1, 2, 3, 4, 5};
  8. int size1 = sizeof(data1); //此處求數組data1所占字節數
  9. int *data2 = data1;
  10. int size2 = sizeof(data2); //此處求指針data2所占字節數
  11. int size3 = GetSize(data1); //data1的地址被賦值給了局部變量data,所以返回指針data所占字節數
  12. printf("%d, %d, %d", size1, size2, size3);
  13. }
  14. //輸出結果為:20, 4, 4
  • 傳遞部分數組
    利用數組以指針形式傳遞的特性,我們可以數組的後本部分給函數。如f(&a[3])f(a+3),將數組a的後7個元素傳遞給了函數f。

3.3 數組與哈希表

數組可以看做一個簡單的哈希表,其哈希函數為為元素的關鍵字key。
常用的哈希函數有:

  1. 除法哈希法

    不太接近2的整數冪的素數適合作為的值
  2. 乘法哈希法

    其中是取的小數部分,即
    建議的變量取值為:
  3. 全域哈希法
    隨機地選擇哈希函數,使之獨立於要存儲的關鍵字。在此不做詳細介紹。

4 編程題

  • 在線編程資源
    牛客網在線編程

  • 二維數組中的查找
    Python:

  1. # -*- coding:utf-8 -*-
  2. class Solution:
  3. # array 二維列表
  4. def Find(self, target, array):
  5. # write code here
  6. r, c = len(array), len(array[0])
  7. i, j = 0, c - 1 //選擇合適的開始位置,右上角和左下角都可以
  8. while (i < r and j >= 0):
  9. if target < array[i][j]:
  10. j = j - 1
  11. elif target > array[i][j]:
  12. i = i + 1
  13. else:
  14. return True
  15. return False //之前將return放在while循環中,一直通不過

C語言:
C語言的實現和Python大同小異,牛客網的OJ系統貌似不支持C語言,此處略過。

5 結語

正如《黑客與畫家》所說,編程語言是程序員的思考方式。思考問題的方式是在具體語言的基礎上進行的,如數組,用C語言思考,我看到的是一片定長連續的內存空間;用Python思考,我看到是隨意組合操作的不定長序列,學習不同的語言可以從不同的角度理解同一個概念,打破自己的思維局限。

劍指offer(1):數組