https://open.kattis.com/problems/oddmanout
有 筆測試資料,每筆測試資料包含一個數字 以及 個數字
對於每一筆測試資料,保證只有一個數字只出現過奇數次,求該數字為何
對於無序的資料,我們可以觀察看看排序之後有沒有特殊的性質可以使用
在這邊我們發現到,當我們將這群數字由小到大排序之後,一樣的數字都會聚集在同一個區域
如此一來,我們就可以直接搜尋過這些相同數字的區域,如果數字個數為奇數,那麼就找到了答案
更進一步的說,我們的步驟會是
輸入的時間複雜度為
排序的時間複雜度為
搜尋答案的時間複雜度為
總時間複雜度
也許你會很直觀的想要先計算看看每個數字出現的次數,然後再檢查次數是奇數或是偶數
而且這樣做得時間複雜度也很棒,只有 而已
但是要注意到題目的數字範圍最大會到 ,所以空間根本不夠使用!
https://zerojudge.tw/ShowProblem?problemid=b966
在一維座標上有 條線段,給定每個線段的左端座標 以及右端座標 ,求所有線段覆蓋的總長度
對於一群無序的資料,可以觀察看看在排序之後有沒有特殊的性質可以使用
在這裡我們發現到,如果我們將所有線段先依照左端點座標由小到大排序,再依照又端點座標由小到大排序,會有很好的性質
因為可以保證對於 第 條線段與第 條線段只會有以下 3 種關係
接下來我們可以嘗試把每一條覆蓋的線段合併,最後計算合併後的總長度即可
針對 3 種情況分別這樣處理:
輸入的時間複雜度為
排序的時間複雜度為
遍歷線段的時間複雜度為
總時間複雜度為
https://open.kattis.com/problems/conformity
http://domen111.github.io/UVa-Easy-Viewer/?11286
在一間大學當中有 個學生,每個學生都可以選擇 5 種課程,並且課程以介於 ~ 之間的數字表示
每個學生選擇的課程會形成一個課程組合
現在學校想要統計每種課程組合有多少學生選擇,並且表揚那些選擇最受歡迎課程組合的學生
輸出總共要表揚多少學生
首先我們要先界定一下相同的課程組合,只要選擇的課程內容相同就是同一個課程組合
但是選擇的先後順序不同會讓我們很困擾,所以首先將所有學生選擇的課程按照其編號由小到大排序好
接下來,對我們來說全部學生的課程組合就是一群無序的資料了,針對這群無序的資料可以觀察排序後有沒有甚麼好的性質可以使用
我們會發現到,當我們將這群資料由小到大排序後,相同的課程組合會被放在一起
那麼我們只需要去統計這幾群相同的序列(相同的課程組合)總共有多少組,然後記錄下最多組的人數總和即可
那麼,要怎麼排序這群無序的資料呢?
一種方法是很直觀的依序依照每個元素的大小來排序,自訂一個 compare function
另一種想法是這樣的,首先觀察到每個學生只能選擇 種課程,並且課程編號都是 位數
那麼,將這些數字組合起來會是一個 位數的數字,範圍在 long long 內
這樣就可以將這一群資料變成一個序列了!
詳細來說,我們的步驟是這樣
輸入時間複雜度為
排序所有學生課程的時間複雜度為
所有學生組合成 15 位數的時間複雜度為
排序所有課程組合的時間複雜度為
遍歷所有課程組合的時間複雜度為
總時間複雜度為
https://open.kattis.com/problems/plantingtrees
有一個園丁要種樹,每棵樹要花上一天的時間播種,並且因為園丁很懶惰,所以一天只會播種一棵樹的種子
聰明的園丁已經知道每棵樹會花幾天成長完成,並且園丁可以自己選擇每顆樹種下的順序
園丁想知道最後一顆樹成長完成的隔天是第幾天(從 1 開始計算)
輸入包含一個正整數 ,接下來有 個正整數 表示每棵樹的成長時間
因為題目當中只有限制每天只能種一棵樹,但是並沒有限制要一顆樹完全成長後才能繼續種植,所以最佳解很顯然的是要從 最大的樹開始種植
也就是說我們先依照種植時間由大到小排序,接下來模擬整個種樹的情況
記錄下當前剩餘成長日的最大值
若 ,就將 更新成
而每一輪的模擬都需要將 遞減,並且將答案遞增
詳細來說,我們的步驟是這樣
輸入時間複雜度為
排序時間複雜度為
遍歷所有成長時間的時間複雜度為
總時間複雜度為
https://open.kattis.com/problems/stickysituation
給定 個正整數數字 ,求是否有任三個數字能組成三角形 ()
對於一群無序的序列,可以觀察看看排序後是否有好的性質
在這一題當中,我們要試圖找到 ,其中 且
前提條件當中的 可以直接透過由小到大排序解決
接下來也許你會想到,我們可以由小到大枚舉三角形的三邊長,然後判斷是否符合
但是真的有必要枚舉所有情況嗎?
假如我們先選擇了三個不連續的數字
如果說這三個不連續的數字能形成三角形,因為是遞增序列,可以保證 也一定會成立
同理, 也會成立
用更簡單的方式來說,我們只需要去枚舉連續的三個元素是否符合即可
也就是只需要檢查 即可
輸入時間複雜度為
排序時間複雜度為
遍歷時間複雜度為
總時間複雜度為
https://open.kattis.com/problems/busnumbers
給一個序列,如果有連續遞增 的子序列 ~ 長度超過 ,那麼就可以化簡成 a_i-a_j
否則正常輸出每個數字
例如有一個序列 經過化簡後會變成 141-143 145
可以化簡的是連續遞增的序列,那麼很容易可以想到先將序列排序
排序之後檢查每個連續的子序列長度,若超過 就輸出化簡的結果,否則正常輸出即可
輸入時間複雜度為
排序時間複雜度為
遍歷時間複雜度為
總時間複雜度為
http://domen111.github.io/UVa-Easy-Viewer/?10327
題目包含多筆測試資料,每筆測試資料第一行有一個正整數 ,接下來有 個數字
求將這個序列由小到大排序需要最少只需要交換多少次
因為這一題的 很小,所以我們可以直接實作 bubble sort,然後計算我們總共交換了幾次
如果說 很大,那就需要用 merge sort 來實作,不過這裡就不實作了
每筆測資輸入時間複雜度為
每筆測資排序時間複雜度為
每筆測資總時間複雜度為
http://domen111.github.io/UVa-Easy-Viewer/?555
現在我們要來玩一場橋牌,一場橋牌當中會有一個玩家負責發牌,並且我們會以方位(N
, E
, S
, W
)來稱呼玩家
發牌會從發牌者的左手邊開始,逆時針方向發牌,直到第 52 張牌被發到發牌玩家
在發牌結束後,我們需要將所有玩家的手牌依照其大小由小到大排序
每張牌都會有一個花色以及一個數字,其大小順序如下
C
< D
< S
< H
2
< 3
< 4
< 5
< 6
< 7
< 8
< 9
< T
< J
< Q
< K
< A
最後依照 S
W
N
E
的順序輸出排序後的手牌
就直接照著題目的意思去模擬
排序的部分自訂一個 compare function
如果要避免寫太多 if-else 來判斷彼此之間的大小,可以預先建立一個表儲存每個元素對應到的數字
只要保證這些數字之間的大小關係跟題目中要求的元素之間大小關係相同即可
預處理時間複雜度為 (可以直接視為常數)
每筆測資輸入時間複雜度為 ()
每筆測資排序時間複雜度為
每筆測資輸出時間複雜度為
每筆測資總時間複雜度為
http://domen111.github.io/UVa-Easy-Viewer/?11321
給定一個長度為 的序列以及一個正整數
根據以下的規則排序
只需要根據題目的意思自訂 compare function 即可
每筆測資輸入時間複雜度為
每筆測資排序時間複雜度為
每筆測資輸出時間複雜度為
每筆測資總時間複雜度為
https://open.kattis.com/problems/sortofsorting
今天有很多字串要做排序,排序的方式是這樣的
要比較兩個字串的大小,我們只需要看這兩個字串的前兩個字元即可
而這兩組的兩個字元所組成的兩組字串比較方式是字典序
如果說這兩組字串的字典序是相同的,那麼就依照原本的順序排即可
補充: 字典序
字典序指的是依照 A-Z
以及 a-z
的方式排列,更廣義的來說,你可以參考 ascii table 每個字所對應的數值,我們就是依照這個大小來比較的
在 C++ 當中,我們可以用 int(c)
來找到字元 c
所對應到的數值
舉例來說,要排序兩個字串 Poincare
以及 Pochhammmer
因為前兩個字的字典序相同,所以依照原本的順序即可 Poincare Pochhammmer
再舉一個例子,要排序兩個字串 Beethoven
以及 Bach
的一個字元的字典序相同,而第二個字的字典序 a
比 e
小,所以放在前面 Bach Beethoven
其實這個排序方式就是所謂的 stable sort, 在 C++ 當中已經有這個函數可以使用
不同的是排序的方式,所以我們要另外寫 compare 函數
比較的方式在前面也有提到就不贅述,詳細可以直接看 code 當中的 cmp()
每筆測資輸入時間複雜度
每筆測資排序時間複雜度
每筆測資輸出時間複雜度
每筆測茲的總時間複雜度約為
https://open.kattis.com/problems/sidewayssorting
一般來說我們排序字串都是由左到右,但是本題要我們由上到下來看
輸入第一行包含兩個正整數 ,表示 row 與 column
接下來有 行,每行 個字元
最後輸出垂直方向由上到下的穩定排序
並且排序過程當中忽略大小寫
舉例來說
從垂直的方向來看,我們會得到三個字串
接下來排序這幾個字串
最後排回原本的橫向
因為排序的方向是垂直的,我們可以直接以垂直的方式儲存這些字串即可
接下來穩定排序過後在改變輸出的方向即可
至於排序的部分,我們可以先把所有要比較的字串先都轉換成小寫之後再來比較大小
每筆測資輸入時間複雜度為
每筆測資初始化時間複雜度為
每筆測資排序時間複雜度為
每筆測資輸出時間複雜度為
每筆測資總時間複雜度約為 ( 很小,可以忽視)
SCIST 演算法 題解