牛客算法-第三章

牛客算法-第三章

1.給定一個無序矩陣,其中有正,有負,有 0,求子矩陣的最大和。

上面求解的是一個無序矩陣的子矩陣。初次看到可能會感覺無從下手。首先,再次應該強調學習的過程中遇到新知識要有把新問題拆解成一個或多個熟悉的問題進行求解。

矩陣其實就是多行數組的組成。所以我們可以進行拆解。
舉例:
二階矩陣
1 2 3 4
4 3 2 1
--------

將上下兩行相加:

5 5 5 5 
在這個過程中,我們也就實現了,將2行n列的矩陣變形爲了一行的數組模式。

這裏有需要提到之前第二章總結的算法原型:求解最大子數組和。

這樣就可以求出對應的最大子矩陣和,二者是一一對應的。

因爲我們在將兩行數據相加的過程中,就已經將二者捆綁在了一起。

在一般的情況下,求解該問題需要用到O(N^6),問題經過這樣的算法之後,可以優化到O(N^3)。

我們這裏提到如何求解一個子矩陣的最大和:

比如一個3行n列矩陣。
1行組成的數組,求解最大子數組和,max更新;
1,2行相加組成的數組,求解最大子數組和,max更新;
1,2,3行相加組成的數組,求解最大子數組和,max更新;
2行組成的數組,求解最大子數組和,max更新;
2,3行相加組成的數組,求解最大子數組和,max更新;
3行組成的數組,求解最大子數組和,max更新。

以上過程,實際上就是遍歷所有可能的“數組構造方式”,也就是求解一個組合,如果有n行,組合一共有n*(n-1)*…*1;

2.給定一個無序矩陣,其中有正,有負,有 0,再給定一個值 k,求累加和小於等於 k 的最
大子矩陣大小,矩陣的大小用其中的元素個數來表示

總結 ,分解部分還是和上面的第一題一樣,將矩陣問題分解爲數組問題的集合。

只不過這裏是換了另外一種算法原型。還是針對數組的:

舉例:
0 1 2 3 4 5
假設 0i的累加和爲sumn[i];0j的累加和爲sum[j]。
也就是說,可以將sum[j]分解爲sum[i]+{i+1…j},
所以,如果存在sum[i]+k>=sum[j];
也就是k>={i+1…j};

此時,我們已經實現了轉化問題。當以j結尾的求小於等於k的最長的子數組時,其實就是也就是求左邊第一個sum[i]>=sum[j]
-k的情況。

比如以j結尾的時候sum[j]=10,我們設定k=4,其實我們求解這個問題的時候,只需要找到從0出發第一個>=sum[j]-k=10-4=6時候的sum[i],就求解出來了。i~j就是我們求解的答案。

而在本題中爲了加快速度,我們設置的累積數組其實是隻增不減的。
舉例如下:

原始數組       3 -1 2 -1 4 -1 4
累加數組       3  2 4  3 7  5 9
改進累加數組    3 3 4 4 7 7 9

通過改進的累積和數組,我們可以通過二分,快速地求出第一個出現大於等於某個數的地方。

3.給定一個無序矩陣,其中只有 1 和 0 兩種值,求只含有 1 的最大的子矩陣大小,矩陣的大
小用其中的元素個數來表示。

總結,首先談大體的解法:

矩陣:
1…
2…
3…
4…
5…

解決的過程就是求解以第一排爲底的情況,求解以第二排爲底的情況。。。求解以第n排爲底的情況。

**關鍵點,把相加的一排的數組的數據想象成一個直方圖。**這時,就是求解最大面積的矩形。

所以,現在的關鍵的算法原型變成:如何在一個直方圖中求解最大的矩形面積。

那麼,這個算法原型是怎樣實現的呢?

以直方圖中某一座標點i爲例,從i向左遍歷,直到找到第一個小於arr[i]的位置l;從i向右遍歷,同樣的,直到找到第一個小於arr[i]的位置r,這時候,以i爲根的矩形不能實現“拓展”了。所以矩形的範圍就是長度爲{l+1,r-1}的範圍,高度是arr[i];

但是,這裏在實際處理的時候,我們用到了數據結構棧。

arr從左到右判斷,如果當前數大於棧頂元素top或者stack.empty()的話,將arr[i]壓入棧中;
否則,如果當前數小於等於top元素的時候,就把棧頂元素彈出。

而在上面的過程中,導致top元素彈出的元素,就是top元素右邊第一個小於等於top的元素就是top元素形成最大矩形的右邊界,而top-1元素就是top元素形成最大矩形的的左邊界。

這裏還有一個注意點就是如果pop 棧頂元素top元素的時候,他是棧裏唯一的一個元素,也就是不存在top-1元素了,此時他的最大矩形的左邊界就是-1.

但是上面爲什麼等於top元素的時候也是彈出呢?因爲這個過程中同樣top值元素得到的矩形範圍不正確,但是因爲相同值,總是連通的。我們求解到最後的一個==top元素值的i座標時,是可以求出這個連通的矩形的最大面積的正確值的。

爲什麼呢?因爲我們的問題是求解最大的矩形,不是爲了求解每一個矩形,我們在這樣的遍歷過程中不會漏掉每一個可能的最大矩形。只不過是,在求解一個大範圍的連同矩形時,中間過程中求解的矩形是錯誤的但是最後的一個同樣值一定會算出這個連通矩形的正確面積。

4.給定一棵完全二叉樹的頭節點 head,求其中的節點個數。

完全二叉樹,就是如果可以遍歷到第i層,那麼0i-1層一定都是滿的,也就是0i-1層就是個滿二叉樹,可以直接公式計算了。

首先,遍歷,最左邊的二叉樹,得到的depth就是max_depth。

然後,遍歷。根結點的最右邊的二叉樹的最左子樹,得到depth2.

如果depth2==depth,也就是說根結點的左子樹是個滿二叉樹。接下來就是遞歸求解根結點的右子樹。

還有另外的一種情況,也就是depth2!-=depth,也就是說根結點的右子樹是個滿二叉樹。接下來就是遞歸求解根結點的左子樹。

總結上面的想法,就是找完全二叉樹總是可以分成兩部分,一部分如果是滿二叉樹,可以根據depth直接公式求解;另一部分如果不是滿二叉樹,就直接遞歸求解。而在這個過程中是如何區分那部分是否使滿二叉樹的呢?就是靠遍歷得到depth,所以複雜度是O((logN)^2)。

5.給定一個字符串類型的數組,其中不含有重複的字符串,如果其中某一個字符串是另一個
字符串的前綴,返回 true;如果沒有任何一個字符串是另一個字符串的前綴,返回 false。

總結,這一道題,涉及到前綴樹,邊上權值是字母。尋找單詞的過程就是遍歷前綴樹的過程。

建樹的過程中進行判斷。
兩種情況符合前綴的情況:
第一種,我總在別人的路上走,我的單詞結束了,還在樹上;
第二種,我總在別人的路上走,走完別人的路了,我的單詞還有剩餘。
第一種情況說明我是之前的單詞的前綴。
第二種情況說明之前的某個或某些單詞是我的前綴。

而針對把字符掛在邊上,所以用hashmap來實現。key當前一個有向邊,value是對應的值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章