数论入门符号_大符号入门指南第2部分
數論入門符號
Well hey there, Chef Remy! Welcome back to the kitchen!
好吧,雷米大廚! 歡迎回到廚房!
Today we’re going to complete our intro to Big O Notation with O(log n), O(n log n), O(2^n) and O(n!) via an impeccable film, Pixar’s Ratatouille. When we last left off, we were preparing our famous ratatouille dish for notorious restaurant critic Anton Ego who was waiting patiently for his meal.
今天,我們將通過無可挑剔的電影皮克斯的《料理鼠王》完成關于O大符號的介紹,其中包括O(log n),O(n log n),O(2 ^ n)和O(n!)。 當我們最后一次離開時,我們正在為臭名昭著的餐廳評論家安東·埃戈(Anton Ego)準備我們著名的料理鼠王料理,他耐心地等待著他的飯菜。
As a refresher, check out the time complexity comparison chart below:
復習一下下面的時間復雜度比較表:
O(log n)記錄時間 (O(log n) Log Time)
Let’s say our waiter received an order from a mysteriously cloaked man (Chef Skinner in disguise! 🕵🏻?♂?) who said “I’ll have what he’s having” in reference to Anton Ego.
假設我們的服務員收到了一個披著神秘衣服的男人的命令(偽裝成廚師斯金納!! ?),他說“我將擁有他所擁有的”。
We know that Anton Ego is seated at table 29, so we will need to look up his food order through his table number. Lucky for us, the table numbers are always kept sorted in our array of orders. This is very helpful, because the restaurant is busy and we can’t keep the customers waiting! We need a quick way to figure out what Anton Ego ordered so that we can double it for the mysterious gentleman customer (coughSkinnercough):
我們知道Anton Ego坐在表29上,因此我們將需要通過他的表號查找他的食物訂單。 對我們來說幸運的是,表號始終按照我們的orders數組進行排序。 這非常有幫助,因為餐廳很忙,我們不能讓顧客等著! 我們需要一種快速的方法來弄清楚Anton Ego訂購了什么,以便為神秘的紳士客戶( coughSkinnercough )加倍購買:
Since the orders are sorted by table number, we can use binary search to cut our search time down. In this method, we take the middle order in the orders array and check for three things:
由于訂單是按table號排序的,因此我們可以使用二進制搜索來減少搜索時間。 在這種方法中,我們將orders數組中的中間訂單作為對象并檢查三件事:
Does this table match the tableNum we’re looking for? If so, great! 🎉Return that order object. If not:
該table是否與我們要查找的tableNum匹配? 如果是這樣,那就太好了! 🎉返回該訂單對象。 如果不:
Is this table less than the tableNum that we’re looking for? If so, eliminate the first half of the array. If not:
該table是否小于我們要查找的tableNum ? 如果是這樣,則消除陣列的前半部分。 如果不:
Is this table greater than the tableNum that we’re looking for? If so, eliminate the second half of the array.
該table是否大于我們要查找的tableNum ? 如果是這樣,請消除陣列的后半部分。
We repeat this process until we find the order object we’re looking for. Since we continuously eliminate half of the array with each recursive step, we say that the time complexity is O(log n) or log time.
我們重復此過程,直到找到所需的訂單對象。 由于我們在每個遞歸步驟中都不斷消除數組的一半,因此我們說時間復雜度為O(log n)或log time 。
This refers to a very math-y term, logarithm, which in Big O Notation looks at the question, “How many 2’s do we multiply together to get n?” If n was equal to 8, it would take 3 operations because 2 * 2 * 2 = 8. If n was 100, it would take 7 operations, and if n was 4,000,000,000 it would take only 32!(Grokking Algorithms)
這指的是一個非常數學的對數項,以Big O表示法著眼于以下問題:“我們將多少個2相乘以得到n ?” 如果n等于8,則將進行3次運算,因為2 * 2 * 2 =8。如果n為100,則將進行7次運算;如果n為4,000,000,000,則將僅進行32次運算( Grokking算法)。
This time complexity is super optimal, and just above O(1) constant time! If your solution is in O(log n) time, you should be pretty pleased! 🙌
這個時間復雜度是超最佳的,剛好超過O(1)恒定時間! 如果您的解決方案是O(log n)時間,那么您應該會很高興! 🙌
O(n log n)線性時間 (O(n log n) Linearithmic Time)
Do you remember how in Part 1 of this Big O series, we wanted to sort the chopped vegetable slices in order to grab the best ones for Anton Ego’s meal? Last time we used a nested for loop which resulted in O(n2) time- not very optimal!
您是否還記得在本Big O系列文章的第1部分中,我們如何將切碎的蔬菜切片分類,以便為Anton Ego的餐點挑選最好的蔬菜切片? 上次我們使用嵌套的for循環導致O(n2)時間-并不是非常理想!
Image credit: Pixar圖片來源:皮克斯If we wanted to cut that time down (because Anton Ego is waiting and his review will make or break this restaurant!! ?), we could use the mergesort algorithm instead. Let’s pretend that each vegetable slice has a rating from 1–n, with 1 being the best slice and n being the worst:
如果我們想減少時間(因為Anton Ego正在等待,并且他的評論將決定這家餐廳的成立與否! ? ),我們可以改用mergesort算法。 假設每個蔬菜切片的等級為1–n,其中1為最佳切片,n為最差切片:
let zucchiniSlices = [20, 11, 25, 3, 14, 5,...]const merge = (arr1, arr2) => {let sorted = [];while (arr1.length && arr2.length) {if (arr1[0] < arr2[0]) {sorted.push(arr1.shift());} else { sorted.push(arr2.shift());}};return sorted.concat(arr1.slice().concat(arr2.slice())); };const mergeSortByBestSlices = veggieSlices => {if (veggieSlices.length <= 1) return veggieSlices;let mid = Math.floor(veggieSlices.length / 2),left = mergeSortByBestSlices(veggieSlices.slice(0, mid)),right = mergeSortByBestSlices(veggieSlices.slice(mid));return merge(left, right); };mergeSortByBestSlices(zucchiniSlices) // [1, 2, 3, 4, 5, 6,...]Mergesort uses a ‘divide and conquer’ approach (similar to binary search), taking an array and breaking it down continuously until each element becomes its own individual sub-array. Then it sorts those sub-arrays in pairs recursively until the entire array is sorted and joined back together again. This article does a great job of explaining the algorithm in further detail.
Mergesort使用“分而治之”的方法(類似于二進制搜索),獲取一個數組并將其連續分解,直到每個元素成為自己的單獨子數組為止。 然后,它將這些子數組成對遞歸地排序,直到整個數組被排序并再次結合在一起。 本文在進一步詳細解釋該算法方面做得很好。
With this approach, the time complexity is O(n log n) because of the 2 main steps involved. The breakdown of the original zucchiniSlices array happens in O(log n) time. Building it back together through sorting requires O(n) time since each element (zucchini slice) must be considered, as well as O(log n) time to merge each sub-array back together. It’s like the equivalent of saying n * log n and it’s also known as linearithmic time.
使用這種方法,由于涉及兩個主要步驟,因此時間復雜度為O(n log n) 。 原始zucchiniSlices數組的分解發生在O(log n)時間。 通過排序將其重新構建在一起需要O(n)時間,因為必須考慮每個元素(西葫蘆切片),還需要O(log n)時間來將每個子數組合并在一起。 這就像說n * log n ,也稱為線性時間。
Since this sort method and time complexity is more optimal than O(n2), we can get those vegetables into the oven and onto Anton Ego’s plate much faster! 👍
由于這種排序方法和時間復雜度比O(n2)最佳,因此我們可以更快地將那些蔬菜放入烤箱并放在Anton Ego的盤子上! 👍
O(2 ^ n)指數時間 (O(2^n) Exponential Time)
The ratatouille is almost ready to be served, but it feels like it’s missing… something. As Chef Remy, you look around and think of 3 herbs that might be a nice finishing touch to add on top: thyme, rosemary and/or marjoram 🌱.
料理鼠王幾乎已經準備好送達了,但感覺好像缺少了……某物。 作為廚師雷米(Remy),您環顧四周,想到3種草藥,它們可能是添加在頂部的一種不錯的點睛之筆:百里香,迷迭香和/或馬郁蘭🌱。
Thinking through the different combinations of herbs would yield O(2^n) possibilities:
通過對草藥的不同組合進行思考將產生O(2 ^ n)可能性:
// with just 1 herb there are 2 options:[""] or ["thyme"]// with 2 herbs there are 4 options:
[""] or ["thyme"] or ["rosemary"] or ["thyme", "rosemary"]// with 3 herbs there are 8 options:
[""] or ["thyme"] or ["rosemary"] or ["marjoram"] or
["thyme", "rosemary"] or ["thyme", "marjoram"] or ["rosemary", "marjoram"] or ["thyme", "rosemary", "marjoram"]
As we can see, the number of options grow in proportion to 2^n:
如我們所見,選項的數量與2 ^ n成正比:
- When n = 1, we have 2^1 possibilities. 當n = 1時,我們有2 ^ 1個可能性。
- When n = 2, we have 2^2 possibilities. 當n = 2時,我們有2 ^ 2的可能性。
- When n = 3, we have 2^3 possibilities, and so on. 當n = 3時,我們有2 ^ 3個可能性,依此類推。
This is called a power set, where the goal is to find all possible subsets of the options given, and the time complexity can be costly. Luckily for Anton Ego, you instinctively know exactly what should be added (a sprig of rosemary of course! 👌) and won’t need to think about every combination. The dish is finally complete!
這稱為功率集,其目標是找到給定選項的所有可能子集,并且時間復雜度可能很高。 幸運的是,對于Anton Ego,您本能地確切知道應該添加什么(當然是一小撮迷迭香!👌),并且無需考慮每種組合。 這道菜終于完成了!
Voila!瞧!In general, you should do your best to avoid O(2^n) or exponential run times as they can blow up very quickly. This one is actually one of the worst time complexities, second only to O(n!).
通常,您應盡力避免O(2 ^ n)或指數運行時間,因為它們會很快爆炸。 實際上,這是最復雜的時間之一,僅次于O(n!)。
O(n!)階乘時間 (O(n!) Factorial Time)
Being that tonight is the grand re-opening of our restaurant, the tables are packed and the servers are very busy running around to attend to each one!
今晚正是我們餐廳的隆重開幕,桌子已經排滿,服務器非常忙碌,到處跑來跑去!
Image credit: Pixar圖片來源:皮克斯Since time is of the essence and people are hungry, our waiter Linguini would like to calculate the best route between the tables so that he’ll walk (or skate) the minimum distance between each table. As it turns out, there are a LOT of possible routes between tables, even if there are only a few!
由于時間至關重要,而且人們很餓,因此我們的服務員Linguini希望計算桌子之間的最佳路線,以便他步行(或滑冰)每個桌子之間的最小距離。 事實證明,即使只有幾個表,表之間也有很多可能的路由!
Possible serving routes between tables表之間可能的服務路線If Linguini is assigned to 5 tables, in order to examine each possible route you would need to do (5 * 4 * 3 * 2 * 1) permutations, which comes out to 120 in total. (Grokking Algorithms) If you were to add one more table to make 6, that would increase to 720 operations (6 * 120). If you add just one more to make 7 tables, that number goes up to 5,040, and if you somehow had 15 tables… that comes out to 1,307,674,368,000 operations! Yikes! 😱
如果將Linguini分配給5個表,則為了檢查每條可能的路線,您需要進行(5 * 4 * 3 * 2 * 1)排列,總計為120。 ( Grokking算法)如果要再增加一張表來制作6,那將增加到720次運算(6 * 120)。 如果僅增加一個就可以創建7個表,那么這個數字將達到5,040,如果您以某種方式擁有15個表,那么結果就是1,307,674,368,000個操作! kes! 😱
This is the absolute worst of the Big O Notation values, known as O(n!) or factorial time. This time complexity should be avoided at all costs, and luckily it’s pretty rare in our day-to-day algorithms.
這是Big O表示法值的絕對最差值,稱為O(n!)或階乘時間。 應該不惜一切代價避免這種時間復雜性,幸運的是,在我們的日常算法中,這種情況非常罕見。
And there you have it! The culmination of our 2-part beginner’s guide to Big O Notation. (Feel free to check out part 1 here, covering O(1), O(n) and O(n2)!)
在那里,您擁有了! 我們的兩部分“大O符號”初學者指南達到了頂峰。 (在此處隨意檢查第1部分,涵蓋O(1),O(n)和O(n2)!)
So how did it go with the ratatouille? Seems as if they liked it. 😊
那么料理鼠王又如何呢? 好像他們喜歡它。 😊
Image credit: Pixar圖片來源:皮克斯翻譯自: https://medium.com/swlh/a-beginners-guide-to-big-o-notation-part-2-c4ede76cea36
數論入門符號
總結
以上是生活随笔為你收集整理的数论入门符号_大符号入门指南第2部分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蒙特卡洛模拟Ising模型
- 下一篇: 青米母公司动力未来登陆新三板 小米生态链