第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

LINQ 中的 OrderBy 和 Take

LINQ 中的 OrderBy 和 Take

C#
翻過(guò)高山走不出你 2022-11-22 15:20:55
我在 Youtube 上看了一些程序員采訪的視頻。其中一個(gè)問(wèn)題是編寫(xiě)一個(gè)返回?cái)?shù)組中第 n 個(gè)最小元素的函數(shù)。在視頻中,我看到一位女士嘗試用 C++ 編寫(xiě)一些重復(fù)代碼,但我認(rèn)為很好,在 C# 中它是一個(gè)襯里:var nth = vals.OrderBy(x => x).Take(i).Last();然后我意識(shí)到我不知道這實(shí)際上是否是一個(gè)好的解決方案,因?yàn)橄乱粋€(gè)問(wèn)題是關(guān)于時(shí)間復(fù)雜度的。我去了文檔,我發(fā)現(xiàn)的是返回的對(duì)象OrderBy具有在枚舉時(shí)執(zhí)行完整延遲排序所需的所有信息。所以我決定對(duì)其進(jìn)行測(cè)試,并MyComparable : IComparable<MyComparable>在 CompareTo 方法中編寫(xiě)了一個(gè)具有單值和靜態(tài)計(jì)數(shù)器的類(lèi): class MyComparable : IComparable<MyComparable>    {        public MyComparable(int val)        {            Val = val;        }        public static int CompareCount { get; set; }        public int Val { get; set; }        public int CompareTo(MyComparable other)        {            ++CompareCount;            if (ReferenceEquals(this, other)) return 0;            if (ReferenceEquals(null, other)) return 1;            return Val.CompareTo(other.Val);        }    }然后我寫(xiě)了一個(gè)循環(huán)來(lái)查找數(shù)組中的第 n 個(gè)元素: static void Main(string[] args)        {            var rand = new Random();            var vals = Enumerable.Range(0, 10000)//                .Reverse() // pesimistic scenario//                .OrderBy(x => rand.Next()) // average scenario                .Select(x => new MyComparable(x))                .ToArray();            for (int i = 1; i < 100; i++)            {                var nth = vals.OrderBy(x => x).Take(i).Last();                Console.WriteLine($"i: {i,5}, OrderBy: {MyComparable.CompareCount,10}, value {nth.Val}");                MyComparable.CompareCount = 0;                var my_nth = vals.OrderByInsertion().Take(i).Last();                Console.WriteLine($"i: {i,5}, Insert : {MyComparable.CompareCount,10}, value {my_nth.Val}");                MyComparable.CompareCount = 0;                my_nth = vals.OrderByInsertionWithIndex().Take(i).Last();                Console.WriteLine($"i: {i,5}, Index  : {MyComparable.CompareCount,10}, value {my_nth.Val}");                MyComparable.CompareCount = 0;                Console.WriteLine();                Console.WriteLine();            }        }
查看完整描述

1 回答

?
精慕HU

TA貢獻(xiàn)1845條經(jīng)驗(yàn) 獲得超8個(gè)贊

好吧,讓我們從唾手可得的果實(shí)開(kāi)始:


您的實(shí)施是錯(cuò)誤的。您需要index + 1從序列中獲取元素。要理解這一點(diǎn),請(qǐng)考慮index = 0并重新閱讀Take.


您的“基準(zhǔn)比較”之所以有效,是因?yàn)檎{(diào)用OrderBy()IEnumerable 不會(huì)修改基礎(chǔ)集合。對(duì)于我們要做的事情,只允許修改底層數(shù)組會(huì)更容易。因此,我冒昧地更改您的代碼以在每次迭代中從頭開(kāi)始生成值。


另外Take(i + 1).Last()相當(dāng)于ElementAt(i). 你真的應(yīng)該使用它。


哦,你的基準(zhǔn)真的沒(méi)有用,因?yàn)槟阈枰牡姆秶鷥?nèi)的元素Take越多,這些算法就越接近彼此。據(jù)我所知,您對(duì) O(n log n) 的運(yùn)行時(shí)分析是正確的。


有一個(gè)解決方案的時(shí)間復(fù)雜度為 O(n)(不是我之前錯(cuò)誤聲明的 O(log n))。這是面試官期待的解決方案。

不管它值多少錢(qián),您在那里編寫(xiě)的代碼都不能移動(dòng)到該解決方案,因?yàn)槟鷮?duì)排序過(guò)程沒(méi)有任何控制權(quán)。


如果你有,你可以實(shí)施Quickselect,(這是這里的目標(biāo)),從而在理論上改進(jìn)你在這里提出的 LINQ 查詢(特別是對(duì)于高索引)。以下是基于您的代碼對(duì) quickselect 維基百科文章中的偽代碼的翻譯


static T SelectK<T>(T[] values, int left, int right, int index) 

   where T : IComparable<T>

{

    if (left == right) { return values[left]; }

    // could select pivot deterministically through median of 3 or something

    var pivotIndex = rand.Next(left, right + 1);

    pivotIndex = Partition(values, left, right, pivotIndex);

    if (index == pivotIndex) {

        return values[index];

    } else if (index < pivotIndex) {

        return SelectK(values, left, pivotIndex - 1, index);

    } else {

        return SelectK(values, pivotIndex + 1, right, index);

    }

}


static int Partition<T>(T[] values, int left, int right, int pivot) 

    where T : IComparable<T>

{

    var pivotValue = values[pivot];

    Swap(values, pivot, right);

    var storeIndex = left;

    for (var i = left; i < right; i++) {

        if (values[i].CompareTo(pivotValue) < 0)

        {

            Swap(values, storeIndex, i);

            storeIndex++;

        }

    }

    Swap(values, right, storeIndex);

    return storeIndex;

}

我運(yùn)行的測(cè)試的非代表性子樣本給出了輸出:


i:  6724, OrderBy:      52365, value 6723

i:  6724, SelectK:      40014, value 6724



i:   395, OrderBy:      14436, value 394

i:   395, SelectK:      26106, value 395



i:  7933, OrderBy:      32523, value 7932

i:  7933, SelectK:      17712, value 7933



i:  6730, OrderBy:      46076, value 6729

i:  6730, SelectK:      34367, value 6730



i:  6536, OrderBy:      53458, value 6535

i:  6536, SelectK:      18341, value 6536

由于我的 SelectK 實(shí)現(xiàn)使用隨機(jī)樞軸元素,因此它的輸出有相當(dāng)多的變化(例如參見(jiàn)第二次運(yùn)行)。它也比標(biāo)準(zhǔn)庫(kù)中實(shí)現(xiàn)的高度優(yōu)化的排序算法差得多。

即使那樣,也有 SelectK 直接優(yōu)于標(biāo)準(zhǔn)庫(kù)的情況,即使我沒(méi)有付出太多努力。


現(xiàn)在用中位數(shù) 3 [1]替換隨機(jī)主元(這是一個(gè)非常糟糕的主元選擇器),我們可以獲得稍微不同的 SelectK 并與 OrderBy 和 SelectK 競(jìng)爭(zhēng)。


我一直在用數(shù)組中的 1m 個(gè)元素與這三匹馬賽跑,使用你已經(jīng)擁有的隨機(jī)排序,在數(shù)組的最后 20% 中請(qǐng)求一個(gè)索引,并得到如下結(jié)果:


Winning counts: OrderBy 32, SelectK 32, MedianOf3 35

Winning counts: OrderBy 26, SelectK 35, MedianOf3 38 

Winning counts: OrderBy 25, SelectK 41, MedianOf3 33

即使對(duì)于 100k 元素并且不將索引限制在數(shù)組的末尾,這種模式似乎仍然存在,盡管沒(méi)有那么明顯:


--- 100k elements

Winning counts: OrderBy 24, SelectK 34, MedianOf3 41

Winning counts: OrderBy 33, SelectK 33, MedianOf3 33

Winning counts: OrderBy 32, SelectK 38, MedianOf3 29

--- 1m elements

Winning counts: OrderBy 27, SelectK 32, MedianOf3 40

Winning counts: OrderBy 32, SelectK 38, MedianOf3 29

Winning counts: OrderBy 35, SelectK 31, MedianOf3 33

一般來(lái)說(shuō),草率實(shí)施的 quickselect 在平均情況下有三分之二的時(shí)間優(yōu)于您的建議......我想說(shuō)這是一個(gè)非常強(qiáng)大的指標(biāo),如果您想了解細(xì)節(jié),這是更好的算法。


當(dāng)然,您的實(shí)現(xiàn)更容易理解 :)


[1] - 取自這個(gè) SO answer的實(shí)現(xiàn),每個(gè)遞歸深度步驟進(jìn)行 3 次比較


查看完整回答
反對(duì) 回復(fù) 2022-11-22
  • 1 回答
  • 0 關(guān)注
  • 160 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)