3.1「Stanford Algorithms」O(n log n) Algorithm for Counting Inversions1 - Part1

In this next series of videos, we'll get some more practice applying the divide and conquer algorithm and design paradigm to various problems.

This will also give us a glimpse of the kinds of application [inaudible] to which it's been successfully applied.

We're gonna start by extending the merge sort algorithm to solve a problem involving counting the number of inversions of an array.

Before we tackle the specific problem of counting the number of inversions in an array, let me say a few words about the divide and conquer paradigm in general.

So again, you've already seen the totally canonical example of divide and conquer, namely merge sort.

So the following three conceptual steps will be familiar to you.

The first step, no prizes for guessing is you divide.

The problem.

Into smaller sub-problems.

Sometimes this division happens only in your mind.

It's really more of a conceptual step than part of your code.

Sometimes you really do copy over parts of the input into say new arrays to pass on to your recursive calls.

The second step, again no prizes here, is you conquer the sub-problems just using recursion.

So for example, in Merge Sort, you conceptually divide the array into two different pieces.

And then you [inaudible] with the conquer or sort to the first half of the array.

And you, you do the same thing with the second half of the array.

Now, of course, it's not quite as easy as just doing these two steps.

Dividing the problem, and then solving the sub problems recursively.

Usually, you have some extra cleanup work after the recursive calls, and to stitch together the solutions to the sub problems into one for the big problem, the problem that you actually care about.

Recall, for example, in Merge Sort, after our recursive calls, the left half of the array was sorted, the right half of the array was sorted.

But we still had to stitch those together.

Merge into a sorted version of the entire array.

So the [inaudible] step is to combine.

The solutions to the subproblem into one problem.

Generally the largest amount of ingenuity happens in the third step.

How do you actually quickly combine solutions to subproblems into one to the original problem? Sometimes you also get some cleverness in the first step with division.

Sometimes it's as simple as just spliting a ray in two.

But there are cases where the division step also has some ingenuity.

Now let's move on to the specific problem of counting inversions and see how to apply this divide and conquer paradygm.

So let begin by defining the problem formally now.

We're given as input an array A with a length N.

And you can define the problem so that the array a contains any ole distinct numbers.

But, let's just keep thing simple and assume that it contains the numbers one through n.

The integers in that range in some order.

That captures the essence of the problem.

And the goal is to compute the number of inversions of this array so what's an inversion you may ask well an inversion is just a pair of array [inaudible] I and J with I smaller than J so that earlier array entry the I entry is bigger than the latter one the Jake one so one thing that should be evident is that if the array contains these numbers in sorted order if the array is simply one two three four all the way up to N then the number of inversions is zero.

The converse you might also want to think through if the array has any other ordering of the numbers between one and N other than the assorted one, then it's going to have a non.

Of zero number of inversions.

Let's look at another example.

So'spose we have an array of six entries.

So the numbers one thru six in the following order.

One, three, five followed by two, four, six.

So how many inversions does this array have? So again what we need to look for are pairs of array entries so that the earlier or left entry is bigger than the later or right entry.

So one example which we see right here would five and two.

Those are right next to each other and out of order, the earlier entry is bigger than the other one.

But there's others, there's three and two for example Those are out of order.

And, five and four are also out of order.

And I'll leave it to you to check that those are the only three pairs that are out of order.

So summarizing the inversions in this array of length six are 3-2, 5-2, and 5-4.

Corresponding to the array entries, 2-4, 3-4, and 3-5.

Pictorially, we can think of it thusly, we can first.

Write down the numbers in order, one up to six.

And then we can write down the numbers again but, ordered in the way that their given in the input array.

So, one three five two four six.

And then we can connect the dots, meaning we connect one to one.

Reconnect two to two, and so on.

It turns out, and I'll leave to for you to, to think this through, that the number of crossing pairs of line segments prescisely correspond to the number of inversions.

So we see that there are one, two, three crossing line segments.

And these are exactly in correspondence with the three inversions, we found earlier.

Five and two, three and two, and five and four.

Now, [inaudible] wanna solve this problem you might ask.

Well there's few reasons that come up.

One would be to have a numerical similarity measure that quantifies how close to [inaudible] lists are to each other.

So for example, suppose I took you and a friend, and I took, identified ten movies that both of you had seen.

And I asked each of you to order, or to rank these movies from your most favorite to your least favorite.

Now I can form an array, and compute inversions.

And it quantifies, in some sense, how dissimilar your two rankings are to each other.

So in more detail, in the first entry of this array, I would put down the ranking that your friend gave to your favorite movie.

So if you had your favorite movie, Star Wars or whatever.

And your friend only thought it was the fifth best out of the ten, then I would write down a five in the first entry of this array.

Generally, I would take your second favorite movie.

I would look at how your friend ranked that.

I would put that in the second entry of the array and so on, all the way up to the tenth entry of the array, where I would put your friend's ranking of your least favorite movie.

Now, if you have exactly identical preferences, if you rank them exactly the same way, the number of inversions of this array would be zero.

And in general, the more inversions this array has, it quantifies that your lists look more and more different from each other.

Now why might you want to do this why might you want to know whether two different people ranked things in the similar way had similar preferences well one reason might be what's called collaborative filtering, probably many of you have had the experience of going to a website and if you've made a few purchases through this website it starts recommending further purchases for you, so one way to solve this problem under the hood, is to look at your purchases look at what you seem to like, find other people who have similar preferences similar history look at things they've bought that you haven't, and then recommend.

New products to you based on what similar customers seemed to have bought.

So this problem captures some of the essence of identifying which customers or which people are similar based on data about what they prefer.

So just to make sure we're all on the same page, let me pause for a brief quiz.

We've already noticed that a given array will have zero inversions, if and only if it's in sorted order.

If it only contains the numbers of one through N in order.

So, on the other side, what is the largest number of inversions an array could possibly have? Let's say, just for an array of size six, like the one in this example here.


在接下來的視頻系列中旨剥,我們將獲得更多實踐,將分而治之算法和設(shè)計范例應(yīng)用于各種問題软族。

這也將使我們了解成功應(yīng)用了哪些應(yīng)用程序[聽不清]绸吸。

我們將從擴(kuò)展合并排序算法開始罩锐,以解決涉及計算數(shù)組反轉(zhuǎn)數(shù)的問題。

在我們解決對數(shù)組中的求逆數(shù)進(jìn)行計數(shù)的特定問題之前葛家,讓我先談一些關(guān)于分而治之的范式喷好。

同樣蚀同,您已經(jīng)看到了分而治之的完全典范示例缅刽,即合并排序啊掏。

因此,您將熟悉以下三個概念性步驟衰猛。

第一步迟蜜,猜猜是沒有獎品的。

問題啡省。

分為較小的子問題娜睛。

有時這種分裂只發(fā)生在您的腦海中懈涛。

這實際上是更多概念性步驟耍铜,而不是代碼的一部分。

有時闪盔,您確實確實將部分輸入復(fù)制到新數(shù)組中结序,以傳遞給遞歸調(diào)用障斋。

第二步,這里也沒有獎品徐鹤,是您僅使用遞歸即可解決子問題垃环。

因此,例如返敬,在“合并排序”中遂庄,您從概念上將數(shù)組分為兩個不同的部分。

然后劲赠,您[聽不清]用征服或排序到數(shù)組的前半部分涛目。

而您,對數(shù)組的后半部分執(zhí)行相同的操作凛澎。

現(xiàn)在泌绣,當(dāng)然,這并不像完成這兩個步驟那樣容易预厌。

劃分問題阿迈,然后遞歸解決子問題。

通常轧叽,在遞歸調(diào)用之后苗沧,您需要進(jìn)行一些額外的清理工作,并將子問題的解決方案組合為一個大問題炭晒,即您真正關(guān)心的問題待逞。

回想一下,例如网严,在“合并排序”中识樱,在我們進(jìn)行遞歸調(diào)用之后,對數(shù)組的左半部分進(jìn)行了排序,對數(shù)組的右半部分進(jìn)行了排序怜庸。

但是我們?nèi)匀槐仨殞⑺鼈兛p合在一起当犯。

合并到整個數(shù)組的排序版本中。

因此割疾,[聽不清]步驟是合并嚎卫。

該子問題的解決方案成為一個問題。

通常宏榕,最大的創(chuàng)造力發(fā)生在第三步拓诸。

您實際上如何快速將子問題的解決方案組合為原始問題?有時麻昼,在除法的第一步中奠支,您也會變得很聰明。

有時抚芦,就像將光線一分為二一樣簡單胚宦。

但是在某些情況下,分割步驟也有一些技巧燕垃。

現(xiàn)在枢劝,讓我們繼續(xù)研究反轉(zhuǎn)計數(shù)的特定問題,并了解如何應(yīng)用這種分而治之卜壕。

因此您旁,讓我們從現(xiàn)在開始正式定義問題開始。

我們將輸入長度為N的數(shù)組A作為輸入轴捎。

并且您可以定義問題鹤盒,以便數(shù)組a包含任何ole互不相同的數(shù)字。

但是侦副,讓我們保持簡單侦锯,并假設(shè)它包含數(shù)字1到n。

該范圍內(nèi)的整數(shù)按一定順序排列秦驯。

這抓住了問題的實質(zhì)尺碰。

而且目標(biāo)是計算此數(shù)組的求逆數(shù),因此您可能會問什么是求逆译隘?求逆只是一對數(shù)組[聽不清] I和J亲桥,且I小于J,因此固耘,較早的數(shù)組入口I入口較大比后一個Jake更重要的一點是题篷,如果數(shù)組按排序順序包含這些數(shù)字,并且該數(shù)組只是一二三四一直到N厅目,則求逆數(shù)為零番枚。

相反法严,您可能還想考慮一下,如果數(shù)組在除N之外的其他任何一個介于1和N之間的數(shù)字葫笼,則它將有一個非整數(shù)深啤。

反轉(zhuǎn)數(shù)為零。

讓我們看另一個例子渔欢。

因此,假設(shè)我們有一個包含六個條目的數(shù)組瘟忱。

因此奥额,數(shù)字按以下順序從一到六。

一访诱,三垫挨,五,然后是二触菜,四九榔,六。

那么這個數(shù)組有多少個反轉(zhuǎn)呢涡相?因此哲泊,我們再次需要尋找的是成對的數(shù)組條目,以便較早或較左的條目大于較晚或較右的條目催蝗。

因此切威,我們在這里看到的一個示例將是五個和兩個。

那些是彼此相鄰且順序混亂的丙号,較早的條目要比另一個條目大先朦。

但是還有其他一些,例如三個和兩個犬缨,它們是亂序的喳魏。

并且,五個和四個也出現(xiàn)故障怀薛。

我將留給您檢查刺彩,以確保只有三對故障。

因此枝恋,總結(jié)此長度為6的數(shù)組中的反演為3-2迂苛、5-2和5-4。

對應(yīng)于數(shù)組條目2-4鼓择、3-4和3-5三幻。

在圖形上,我們可以這樣思考呐能,我們可以首先念搬。

依次寫下數(shù)字抑堡,最多1個。

然后我們可以再次寫下數(shù)字朗徊,但是按照輸入數(shù)組中給定的方式排序首妖。

因此,一三五二四六爷恳。

然后我們可以連接點有缆,這意味著我們一對一地連接。

重新連接兩個到兩個温亲,依此類推棚壁。

事實證明,我將讓您仔細(xì)考慮一下栈虚,線段的交叉對的數(shù)量精確地對應(yīng)于反轉(zhuǎn)的數(shù)量袖外。

因此,我們看到有1魂务、2曼验、3個交叉線段。

這些恰好與我們先前發(fā)現(xiàn)的三個反演相對應(yīng)粘姜。

五和二鬓照,三和二,五和四孤紧。

現(xiàn)在颖杏,[聽不清]想解決您可能會問的問題。

好吧坛芽,有幾個原因留储。

一種方法是采用數(shù)值相似性度量,以量化[聽不清]列表彼此之間的接近程度咙轩。

例如获讳,假設(shè)我?guī)愫鸵粋€朋友,然后帶我確定了你們倆都看過的十部電影活喊。

我請你們每個人訂購丐膝,或?qū)⑦@些電影從您最喜歡的到最不喜歡的排列。

現(xiàn)在钾菊,我可以形成一個數(shù)組帅矗,并計算反轉(zhuǎn)。

從某種意義上說煞烫,它量化了兩個排名之間的差異浑此。

因此,更詳細(xì)地講滞详,在該數(shù)組的第一個條目中凛俱,我將放下您的朋友對您最喜歡的電影的排名紊馏。

因此,如果您有自己喜歡的電影蒲犬,《星球大戰(zhàn)》或其他電影朱监。

而您的朋友只認(rèn)為這是十個最佳中的第五個,那么我會在該數(shù)組的第一項中寫下一個五個原叮。

通常赫编,我會拍第二部您喜歡的電影。

我會看看你的朋友如何評價的奋隶。

我會將其放在數(shù)組的第二個條目中擂送,依此類推,一直到數(shù)組的第十個條目达布,然后將您的朋友在您最不喜歡的電影中的排名放在此處团甲。

現(xiàn)在逾冬,如果您具有完全相同的首選項黍聂,如果以完全相同的方式對它們進(jìn)行排名,則此數(shù)組的反轉(zhuǎn)數(shù)將為零身腻。

通常产还,此數(shù)組的反轉(zhuǎn)次數(shù)更多,它可以量化列表之間的差異越來越大嘀趟。

現(xiàn)在脐区,為什么要執(zhí)行此操作,為什么要知道兩個不同的人是否以相似的方式對事物進(jìn)行排名她按,是否具有相似的偏好牛隅?一個原因可能就是所謂的協(xié)作過濾,也許你們中的許多人都有訪問網(wǎng)站的經(jīng)驗如果您通過該網(wǎng)站進(jìn)行了幾次購買酌泰,它就會開始為您推薦進(jìn)一步的購買媒佣,因此,解決這個問題的一種方法是查看您的購買陵刹,看看您的喜好默伍,找到其他有購買意愿的人相似的偏好相似的歷史記錄會查看他們購買的,您沒有的東西衰琐,然后推薦也糊。

根據(jù)相似客戶購買的商品為您提供新產(chǎn)品。

因此羡宙,此問題捕獲了一些本質(zhì)狸剃,這些本質(zhì)是基于有關(guān)他們偏愛的數(shù)據(jù)來識別哪些客戶或哪些人是相似的。

因此狗热,為了確保我們都在同一頁面上捕捂,讓我暫停一下簡短的測驗瑟枫。

我們已經(jīng)注意到,給定數(shù)組只有在按排序順序時才具有零反轉(zhuǎn)指攒。

如果僅按順序包含1到N的數(shù)字慷妙。

那么,另一方面允悦,數(shù)組可能具有的最大反轉(zhuǎn)數(shù)是多少膝擂?假設(shè)僅是大小為6的數(shù)組,例如此處的示例隙弛。


O(n log n) Algorithm for Counting Inversions I - Question 1

What is the largest-possible number of inversions that a 6-element array can have?

A 15

B 21

C 36

D 64

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末架馋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子全闷,更是在濱河造成了極大的恐慌叉寂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件总珠,死亡現(xiàn)場離奇詭異屏鳍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)局服,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進(jìn)店門钓瞭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人淫奔,你說我怎么就攤上這事山涡。” “怎么了唆迁?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵鸭丛,是天一觀的道長。 經(jīng)常有香客問我唐责,道長鳞溉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任妒蔚,我火速辦了婚禮穿挨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肴盏。我一直安慰自己科盛,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布菜皂。 她就那樣靜靜地躺著贞绵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恍飘。 梳的紋絲不亂的頭發(fā)上榨崩,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天谴垫,我揣著相機(jī)與錄音,去河邊找鬼母蛛。 笑死翩剪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的彩郊。 我是一名探鬼主播前弯,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼秫逝!你這毒婦竟也來了恕出?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤违帆,失蹤者是張志新(化名)和其女友劉穎浙巫,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刷后,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡的畴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惠险。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苗傅。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡抒线,死狀恐怖班巩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嘶炭,我是刑警寧澤抱慌,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站眨猎,受9級特大地震影響抑进,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睡陪,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一寺渗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兰迫,春花似錦信殊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至据德,卻和暖如春鳄乏,著一層夾襖步出監(jiān)牢的瞬間跷车,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工橱野, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留朽缴,地道東北人。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓水援,卻偏偏與公主長得像不铆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子裹唆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,974評論 2 355