Verimli bir sıralı listenin sıralı toplamları olsun

oy
17

Sen numaraların artan bir listesi var, bu listedeki her iki sayının toplamlarının artan listesini almak için aklınıza gelebilecek en verimli algoritma budur. Ortaya çıkan listede çoğaltır alakasız, bunları kaldırmak veya isterseniz bunları önleyebilirsiniz.

Açık olmak gerekirse, ben algoritma ilgileniyorum. istediğiniz herhangi bir dilde ve paradigma kod göndermek için çekinmeyin.

Oluştur 03/08/2008 saat 22:08
kaynak kullanıcı
Diğer dillerde...                            


8 cevaplar

oy
12

2018 itibariyle düzenleyin: Muhtemelen bu okuma durdurmak gerekir. (Bu kabul edilmektedir Ama bunu silemezsiniz.)

Böyle toplamları dışarı yazarsanız:

1 4  5  6  8  9
---------------
2 5  6  7  9 10
  8  9 10 12 13
    10 11 13 14
       12 14 15
          16 17
             18

Sen fark edeceksiniz beri M [i, j] <= M [i, j + 1] ve M [i, j] <= M [i + 1, j], o zaman sadece üst sol "incelemek gerekir köşeler" ve en düşük olanı seçin.

Örneğin

  • Sadece 1 sol üst köşesi, 2 almak
  • sadece 1, 5 almak
  • 6 ya da 8, 6 almak
  • 7 ya da 8, 7 almak
  • 9 ya da 8, 8 çekme
  • 9 ve 9, hem de çekme :)
  • 10 ya da 10 ya da 10, tüm çekme
  • 12 ya da 11, 11 çekme
  • 12 ya da 12, her iki çekme
  • 13 ya da 13, her iki çekme
  • 14 ya da 14, her iki çekme
  • 15 ya da 16, 15 çekme
  • Sadece 1, 16 çekme
  • sadece 1, 17 çekme
  • sadece 1, 18 çekme

Eğer varsa Tabii ki, çok sol üst köşesinden o zaman bu çözüm devolves.

Her M için toplamları hesaplamak zorunda çünkü bu sorun Ω (n²) eminim [i, j] - Birisi toplamı için daha iyi bir algoritma sahip olmadıkça :)

Cevap 18/09/2008 saat 22:41
kaynak kullanıcı

oy
4

Aksine bu dışarı kodlama yerine, ben o adımda-kodu, yalancı ve gerekirse daha iyi programcılar benim mantığı delik aç, böylece benim mantığı açıklamak rakam.

İlk adımda biz numaralar n uzunluğundaki bir liste ile başlar. Her numara için biz kendisine bir sayı ekleyerek değildir çünkü n uzunluğundaki-1 listesini oluşturmak gerekir. Sonuna kadar n (n ^ 2) sürede oluşturulan listeleri kriteri kadar bir listesi vardır.

step 1 (startinglist) 
for each number num1 in startinglist
   for each number num2 in startinglist
      add num1 plus num2 into templist
   add templist to sumlist
return sumlist 

listeleri tasarımı ile dizildi çünkü 2. adımda her liste birleştirme birlikte ziyade sürü mergesorting tarafından bir mergesort yapmak basitçe (a sıralı listedeki her elemana bir numara ekleyebilir ve listesi hala sıralanır). Sonunda bu O (n ^ 2) zaman gerekir.

step 2 (sumlist) 
create an empty list mergedlist
for each list templist in sumlist
   set mergelist equal to: merge(mergedlist,templist)
return mergedlist

Birleştirme yöntemi, daha sonra yinelenen toplamlar olmadığından emin olmak için bir çek ile normal bir birleştirme adım olacaktır. Herkes mergesort bakabilir çünkü bu out yazılmaz.

Yani benim çözüm var. Tüm algoritma O (n ^ 2) zamandır. herhangi bir hata veya iyileştirme işaret çekinmeyin.

Cevap 04/08/2008 saat 00:06
kaynak kullanıcı

oy
2

Sen Python iki çizgi ile giriş yapabilirsiniz

allSums = set(a+b for a in X for b in X)
allSums = sorted(allSums)

Bu maliyeti n ^ 2 (set için belki fazladan günlük faktörü?) 'dir ler kümesinin boyutu sıralama için yineleme ve s * günlüğüne (ler) için.

kümesinin boyutu, X = [1,2,4, ..., 2 ^ n], örneğin (n-1) / 2 n x kadar büyük olabilir. Bu listeyi oluşturmak istiyorsanız bu en kötü durumda en az n ^ 2/2 sürer Yani bu çıkışın boyutudur beri.

Eğer Fredrickson ve Johnson tarafından sıralanmış X + Y matrisleri için bir seçme algoritması kullanılarak O'da bunu yapabilirsiniz sonucunun ilk k elemanlarını (kn) seçmek istiyorsanız Ancak ( kanlı detayları için buraya bakınız) . Bu muhtemelen hesaplama yeniden kullanarak çevrimiçi olarak oluşturmak ve bu set için etkin bir jeneratör almak için değiştirilebilir rağmen.

@deuseldorf Peter hakkında bazı karışıklıklar Ciddi şüphe deuseldorf "n faktöryel" anlamına (! n) yoktur ama sadece "n (çok heyecanlı)!"

Cevap 11/08/2008 saat 15:47
kaynak kullanıcı

oy
1

Ne yaparsanız yapın, ne girdi değerlerine ek kısıtlamalar olmadan, size sayıların tüm çiftleri arasında yineleme sahip olduğumuzdan, O (n ^ 2) daha iyi yapamaz. yineleme (siz (n log n) veya daha hızlı O'da yapabilirsiniz) sıralama hakim olacak.

Cevap 18/09/2008 saat 23:15
kaynak kullanıcı

oy
1

Bu soru şimdi yaklaşık bir gün boyunca beynimi bozucu olmuştur. Muhteşem.

Neyse, kolayca ondan n ^ 2 doğadan elde edemezsiniz, ancak her eleman eklemek için aralık bağlı beri, birleştirme ile biraz daha iyi yapabilir.

Eğer üretmek tüm listeleri bakarsak, bunlar şu form var:

(a[i], a[j]) | j>=i

bunu 90 derece döner ise elde edersiniz:

(a[i], a[j]) | i<=j

Şimdi, birleştirme işlemi iki listeyi alarak gerektiğini ive i+1(ilk üyesi daima olduğu listelerine uygun a[i]ve a[i+1]) Öge eklemek aralığı bağlı olabilir (a[i + 1], a[j])listeye iyere göre (a[i], a[j])ve konumu (a[i + 1], a[j + 1]).

Bu bakımından tersten birleştirme gerektiği anlamına gelir j. Eğer genelinde bu kaldıraç miyim (henüz) bilmiyoruz jyanı, ama mümkün görünüyor.

Cevap 21/08/2008 saat 19:16
kaynak kullanıcı

oy
1

SQL:

create table numbers(n int not null)
insert into numbers(n) values(1),(1), (2), (2), (3), (4)


select distinct num1.n+num2.n sum2n
from numbers num1
inner join numbers num2 
    on num1.n<>num2.n
order by sum2n

C # LINQ:

List<int> num = new List<int>{ 1, 1, 2, 2, 3, 4};
var uNum = num.Distinct().ToList();
var sums=(from num1 in uNum
        from num2 in uNum 
        where num1!=num2
        select num1+num2).Distinct();
foreach (var s in sums)
{
    Console.WriteLine(s);
}
Cevap 09/08/2008 saat 00:05
kaynak kullanıcı

oy
1

Birlikte gelen en iyi, birlikte a-la birleştirme tür satırlar her çiftin toplamlarının bir matris üretmek ve ardından birleştirme etmektir. Ben çok daha verimli bir çözüm ortaya çıkaracaktır bazı basit fikir kaçırıyorum gibi hissediyorum.

Haskell Benim algoritması,:

matrixOfSums list = [[a+b | b <- list, b >= a] | a <- list]

sortedSums = foldl merge [] matrixOfSums

--A normal merge, save that we remove duplicates
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = case compare x y of
    LT -> x:(merge xs (y:ys))
    EQ -> x:(merge xs (dropWhile (==x) ys))
    GT -> y:(merge (x:xs) ys)

Ben küçük bir iyileşme, tembel akış tabanlı kodlama daha yumuşak olanı buldum. Bunun yerine sütunlar eşleştirmek-bilge birleştirme, bir kerede hepsini birleştirmek. avantajı hemen listenin elemanlarını almaya başlamak varlık.

-- wide-merge does a standard merge (ala merge-sort) across an arbitrary number of lists
-- wideNubMerge does this while eliminating duplicates
wideNubMerge :: Ord a => `a` -> [a]
wideNubMerge ls = wideNubMerge1 $ filter (/= []) ls
wideNubMerge1 [] = []
wideNubMerge1 ls = mini:(wideNubMerge rest)
    where mini = minimum $ map head ls
          rest = map (dropWhile (== mini)) ls

betterSortedSums = wideNubMerge matrixOfSums

Eğer toplamlar tüm kullanacağız biliyorum ve hiçbir avantajı daha erken bazıları almak için varsa Ancak, 'gitmek foldl merge []daha da hızlı olarak,'.

Cevap 03/08/2008 saat 22:36
kaynak kullanıcı

oy
-4

Eğer gerçekten dil agnostik çözüm arıyorsanız Eğer döngü ve bazı koşullar için bir ile sıkışmış olacak çünkü o zaman bence fena halde hayal kırıklığına uğrayacaktır. Eğer işlevsel dil veya işlevsel dil özelliklerine o açtı ancak sonra burada arkadaşlarım Ruby, Lisp, Erlang ve diğerlerinde zarif örnekleriyle bu sayfayı doldurabilir (LINQ sana bakıyorum).

Cevap 03/08/2008 saat 22:24
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more