Hatékonyan kap kiválogatott összegeket rendezett listáját

szavazat
17

Van egy emelkedő számok listája, ami a leginkább hatékony algoritmust lehet gondolni, hogy az emelkedő listája összegeket minden második szám a listára. Kétszer szerepel a kapott listában nem helytálló, akkor távolítsa el őket, vagy elkerülni őket, ha úgy tetszik.

Ahhoz, hogy tiszta, Érdekelne, az algoritmus. Nyugodtan tegye kódot bármilyen nyelven és paradigmát, hogy tetszik.

A kérdést 03/08/2008 22:08
a forrás felhasználó
Más nyelveken...                            


8 válasz

szavazat
-4

Ha keres egy igazán nyelv-független megoldás, akkor lesz nagyon csalódott véleményem, mert akkor kell ragasztani a hurok, és néhány feltételes. Ha azonban megnyitotta azt a funkcionális nyelvek, illetve funkcionális nyelv jellemzői (én néztem meg LINQ), majd kollégáim itt kitöltheti ezt az oldalt elegáns példákat Ruby, Lisp, Erlang, és mások.

Válaszolt 03/08/2008 22:24
a forrás felhasználó

szavazat
1

A legjobb, amit elér az, hogy egy mátrix összegek az egyes párok, majd egyesíteni a sorok együtt, a-la merge sort. Úgy érzem, hogy hiányzik néhány egyszerű betekintést, mely felfedi egy sokkal hatékonyabb megoldás.

Saját algoritmus, Haskell:

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)

Találtam egy kisebb javulás, az egyik, hogy sokkal alkalmasabb arra lusta stream-alapú kódolás. Ahelyett, hogy egyesíti a oszlopokban páronként, összeolvad mindet egyszerre. Az előnye az, hogy elkezd szerzés lista elemei azonnal.

-- 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

Azonban, ha tudod, hogy fogsz használni az összes összegek, és nincs előnye, hogy néhány közülük korábban megy „ foldl merge []”, mivel ez gyorsabb.

Válaszolt 03/08/2008 22:36
a forrás felhasználó

szavazat
4

Ahelyett kódoló ezt ki tudom képzelni én ál-kód azt lépéseket, és megmagyarázni a logika, hogy a jobb programozók lök lyukak az én logika, ha szükséges.

Az első lépésben elindul egy listát a számok n hosszúságú. Minden egyes szám létre kell hoznunk egy listát a hossza n-1 becuase nem vagyunk hozzá egy számot is. Végére van egy lista a n rendezve listákat, hogy keletkezett O (n ^ 2) időt.

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 

A 2. lépés, mert a listákat sorolva mintával (Szám hozzáadása minden elemét egy rendezett listát, és a listát továbbra is rendezve) akkor egyszerűen nem egy mergesort összevonásával egyes listák együtt ahelyett mergesorting az egészet. A végén ez O (n ^ 2) időt.

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

Az egyesítési módszer az lenne, akkor a normális egyesítési lépést egy csekket, hogy megbizonyosodjon arról, hogy nincsenek ismétlődő összegeket. Nem írok ki ezt, mert bárki felnéz mergesort.

Tehát az én megoldás. A teljes algoritmus O (n ^ 2) időt. Nyugodtan rámutatni a hibákat vagy fejlesztéseket.

Válaszolt 04/08/2008 00:06
a forrás felhasználó

szavazat
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);
}
Válaszolt 09/08/2008 00:05
a forrás felhasználó

szavazat
2

Megteheti ezt a két vonalat Python

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

Ennek költsége n ^ 2 (talán egy extra log tényező a beállított?) Az iteráció és s * log (ek) számára a rendezési ahol s a mérete a beállított.

A méret a beállított lehet olyan nagy, mint n * (n-1) / 2, például, ha X = [1,2,4, ..., 2 ^ n]. Tehát ha azt akarjuk, hogy létrehoz a lista fog tartani legalább n ^ 2/2 a legrosszabb esetben, mivel ez a méret a kimenetet.

Azonban ha azt szeretnénk, hogy válassza ki az első k elemet az eredmény, akkor ezt az O (kn) egy kiválasztási algoritmus szerint rendezve X + Y mátrixok által Frederickson és Johnson ( lásd itt a véres részleteket) . Bár ez valószínűleg módosítani kell generálni őket az interneten újrahasznosításával számítást, és kap egy hatékony generátor ezt meg.

@deuseldorf, Peter Van némi zavart a (n!) Én komolyan kétséges deuseldorf azt jelentette: „n faktoriális”, hanem egyszerűen „n, (nagyon izgatott)!”

Válaszolt 11/08/2008 15:47
a forrás felhasználó

szavazat
1

Ezt a kérdést már wracking agyam körülbelül egy nap most. Fantasztikus.

Egyébként, akkor nem kap el a n ^ 2 természete könnyen, de meg lehet csinálni valamivel jobb az egyesítés, mert akkor kötött tartományban beszúrni minden eleme.

Ha megnézzük az összes listát generál, ezek a következő formában:

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

Ha flip 90 fokkal, kapsz:

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

Most, az egyesítési folyamatot kell figyelembe két listát iés i+1(amelyek megfelelnek a listára, ha az első elem mindig a[i]és a[i+1]), akkor köteles a tartomány beszúrni elem (a[i + 1], a[j])a listán ia helye (a[i], a[j])és a helyét (a[i + 1], a[j + 1]).

Ez azt jelenti, hogy meg kell egyesíteni fordított szempontjából j. Nem tudom, hogy (még), ha képes kihasználni ezt az egész jis, de úgy tűnik, lehetséges.

Válaszolt 21/08/2008 19:16
a forrás felhasználó

szavazat
12

Szerkessz 2018: Meg kellene megállítani ezt olvasod. (De nem tudom törölni, mert elfogadták.)

Ha írsz ki az összegeket, mint ez:

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

Észre fogod venni, hogy mivel M [i, j] <= M [i, j + 1] és M [i, j] <= M [i + 1, j], akkor csak meg kell vizsgálnunk a bal felső " sarkok”és válassza ki a legalacsonyabb.

például

  • Csak 1 bal felső sarokban vedd 2
  • csak 1, 5 felvenni
  • 6 vagy 8, pick 6
  • 7 vagy 8, vegye 7
  • 9, illetve 8, vegye 8
  • 9 vagy 9, vegye mindkét :)
  • 10, 10 vagy 10, vegye minden
  • 12 vagy 11, vegye 11
  • 12 vagy 12, vegye mindkét
  • 13 vagy 13, vegye mindkét
  • 14 vagy 14, vegye mindkét
  • 15 vagy 16, vegye 15
  • csak 1, vedd 16
  • csak 1, vedd 17
  • csak 1, vedd 18

Persze, ha van sok a bal felső sarkokat, akkor ez a megoldás hárul.

Biztos vagyok benne, ez a probléma Ω (Nl), mert meg kell számítani az összegeket az egyes M [i, j] - kivéve, ha valakinek van egy jobb algoritmust az összegzés :)

Válaszolt 18/09/2008 22:41
a forrás felhasználó

szavazat
1

Nem számít, mit csinál, anélkül, hogy további megszorítások a bemeneti értékeket, akkor nem jobb, mint az O (n ^ 2), egyszerűen azért, mert van, hogy végiglépdelni számpárok. Az iteráció fog dominálni válogatása (amit tehetünk O (n log n) vagy gyorsabb).

Válaszolt 18/09/2008 23:15
a forrás felhasználó

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