劍指offer 以空間換時間練習

2021-10-06 02:31:52 字數 2958 閱讀 8991

1、題目要求

我們把只包含因子2、3、5的數稱作醜數,求按從小到大的順序的第1500個醜數。例如,6、8都是醜數,但14不是,因為它包含因子7.習慣上我們把1當做第乙個醜數。

2、題目分析

方法一:

首先,我們再來仔細分析一下醜數的概念,因為2,3,5是醜數的因子,那麼就可以說明任意乙個醜數對其中乙個因子求余為0。醜數只能被2,3,5整除,也就是說,如果能被5整除,就除以連續5,如果最後得到的是1,那麼這個數就是醜數。

因此,我們可以寫出下面的函式來判斷乙個數是不是醜數

bool

isugly

(int number)

intgetuglynumber

(int index)

}return number;

}

但是這種方法最大的問題就是每個整數都要計算,即使乙個整數不是醜數,我們還是要對其進行除法和求餘操作。因此這種演算法的時間效率不是很高。

方法二:建立陣列儲存已經找到的醜數,用空間換時間的解法

基於上述演算法的弊端,我們要找到一種只計算醜數的方法,而不在非醜數的整數上花費時間。我們可以建立乙個陣列,裡面的數字是排好序的醜數。每個醜數都是前面的醜數乘以2、3或者5得到的。我們把已有最大的醜數記做m,接下來分析如何生成下乙個醜數,該醜數肯定是前面某乙個醜數乘以2、3或者5的結果,所以我們把已有的醜數乘以2得到m2,把已有的醜數乘以3得到m3,把已有的醜數乘以5得到m5。最後比較三個數的最小值。**實現如下:

int

min(

int number1,

int number2,

int number3)

intgetuglynumber

(int index)

int ugly = puglynumber[nextuglyindex -1]

;delete

puglynumber;

return ugly;

}

1、題目要求在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對,輸入乙個陣列,求出這個陣列中的逆序對的總數。例如:在陣列中,一共存在5個逆序對,分別是(7,6)、(7,5)、(7,4)、(6,4)和(5,4)。

2、題目分析

方法一:

對這道題最直觀的解法可能就是順序掃瞄整個陣列,每掃瞄到乙個數字,逐個比較該數字後面的數字的大小,求出這個陣列中的逆序對。但是這種方法的效率不高,時間複雜度可達o(n^2)

方法二:一種以空間換時間的解法

具體的分析我們還是以陣列來進行分析。我們先考慮比較兩個相鄰的數字。總的概括來說就是乙個先分解再組合的過程,類似於歸併排序。如下圖所示:

過程1和過程2就是乙個不斷分解的過程,當分解成只有乙個元素的時候就要開始合併了,合併的過程是進行排序的合併,並且要統計其中的逆序對。

現在最關鍵的就是過程4合併、排序並統計逆序對的過程。這時,我們需要定義三個指標,p1,p2和p3,其中p1和p2分別指向兩個陣列的末尾,p3指向輔助陣列的末尾。如下圖a所示。每次比較兩個指標指向的數字,如果p1指向的數字大於p2指向的數字,則構成了逆序對,並且逆序對的數目為第二個子陣列中剩餘數字的個數(本題中為2)。接下來把p1,p2所指的數字中較大的數字從後往前複製到下面的輔助陣列中,然後對應的指標往前挪動一位,如面b圖所示。然後再進行上述的比較過程,此時由於p1指向的數字小於p2所指向的數字,所以是不構成逆序對的,但是同樣將p1,p2所指的數字中較大的數字從後往前複製到下面的輔助陣列中,然後對應的指標往前挪動一位,如面c圖所示

有了上述詳細的討論,我們就可以總結出統計逆序對的過程:先把陣列分隔成子陣列,統計出子陣列內部的逆序對數目,然後再統計出兩個相鄰子陣列之間的逆序對的陣列。在統計逆序對的過程中,還需要對陣列進行排序。所以寫出**實現如下:

int

inversepairscore

(int

* data,

int* copy,

int start,

int end)

int length =

(end - start)/2

;int left =

inversepairscore

(data, copy, start, start + length)

;int right =

inversepairscore

(data, copy, start + length, end)

;//i初始化為前半段的最後乙個數字的下標

int i = start + length;

//jj初始化為後半段的最後乙個數字的下標

int j = end;

int indexcopy = end;

int count =0;

while

(i >= start && j >= start + length +1)

else

}for

(; i >= start; i--

) copy[indexcopy--

]= data[i]

;for

(; j >= start + length +

1; j--

) copy[indexcopy--

]= data[j]

;return count + left + right;

}int

inversepairs

(int

* data,

int length)

以空間換時間經典演算法

以前看過一篇文章 優化c 常用的幾招 作者提到的第一招就是 以空間換時間 還舉了乙個例子,由於比較經典,引用一下 電腦程式中最大的矛盾是空間和時間的矛盾,那麼,從這個角度出發逆向思維來考慮程式的效率問題,我們就有了解決問題的第1招 以空間換時間。比如說字串的賦值 方法a 通常的辦法 define l...

以空間換時間的計數排序

我們前面學習的插入 歸併 堆和快速排序都是比較排序,即在排序的最終結果中,各元素的次序依賴於它們之間的比較。我們說過比較排序有時間下界,即nlgn,如果我們需要乙個時間複雜度為o n 的排序演算法,要怎麼辦?計數排序就是比較好的選擇。計數排序的基本思想是 對每乙個輸入的元素x,確定小於x的元素個數。...

以時間換空間,聯合主鍵 舉例

在建立資料庫是,以空間換時間應該怎麼理解呢,舉例 建設你要建立乙個商品的資料庫,肯定要有乙個商品表goods,這個商品有喝多宣傳,那肯定還要有乙個表goods image表,而且乙個 商品可以對應很多,所以是一對多的關係 但是這個商品有乙個主宣傳,那麼如果將主 宣傳也新增到goods image的表...