En yakın mesafelerin toplamını bulun


10

Bu görev için kodunuz girdi olarak X ve Y tamsayılarının iki sıralı dizisini almalıdır. X'deki her tam sayı ile Y'deki en yakın sayı arasındaki mutlak mesafelerin toplamını hesaplamalıdır.

Örnekler:

X = (1 5,9)
Y = (3,4,7)

Mesafe 2 + 1 + 2'dir.

X = (1,2,3)
Y = (0,8)

Mesafe 1 + 2 + 3'tür.

Kodunuz uygun olan herhangi bir şekilde girdi alabilir.

Temel kısıtlama, kodunuzun iki dizinin uzunluğunun toplamı olarak doğrusal zamanda çalışması gerektiğidir. . (İki tamsayı eklemenin sabit zaman aldığını varsayabilirsiniz.)


Diziler yerine listeleri veya akışları kullanabilir miyiz?
Ad Hoc Garf Hunter

@CatWizard Evet yapabilirsiniz!
Anush

1
Nasıl olduğunu 1 + 2 + 3türetilmiştir X = (1,2,3)ve Y = (0,8)?
guest271314

1
@ guest271314 yakın iki numarası her biri 1, 2ve 3de YIS 0. Böylece farklar 1-0, 2-0, 3-0.
dylnan

1
@FreezePhoenix her iki liste de sıralandığından bunu O (n + m) olarak yapabilirsiniz, çünkü listesinde yineleme yaparsınız , her bir öğeyi bir kez ziyaret edersiniz ve X i'ye en yakın Y j öğesini izlediğiniz sürece , bunlardan biri X i + 1'e en yakın olduğu için Y j ve Y j + 1'e karşı kontrol edinXYjXbenYjYj+1Xben+1
Giuseppe

Yanıtlar:


6

Haskell , 70 64 bayt

a%b=abs$a-b
x@(a:b)#y@(c:d)|e:_<-d,a%c>a%e=x#d|1>0=a%c+b#y
_#_=0

Çevrimiçi deneyin!

açıklama

İlk (%)olarak iki sayı arasındaki mutlak fark olarak tanımlarız . Sonra (#)ilginç bir fonksiyon olarak tanımlıyoruz . İlk satırda, her iki liste boş olmadığında eşleşiriz:

x@(a:b)#(c:d:e)

Buradan yeni İlk durumda biz bağlamak diçin e:_birlikte e:_<-d. Bu d, boş olmamasını sağlar ve ilk öğesini olarak ayarlar e.

Ardından, ( ) öğesinin ikinci öğesi, X ( ) öğesinin ilk öğesinden ( ) ilk öğeden daha yakınsa , Y'nin ilk öğesinin kaldırılmasına ve aynı X ile tekrar çağrılmasına geri dönülür .YecXax#dYX

Deseni eşleştirirsek, ancak yaptığımız koşulu geçmezsek:

a%c+b#y

Ki, ilk öğeyi kaldırır ve ilk öğesinden bunun mutlak farkı ekleyen X kalan sonuca.XX

Son olarak, kalıpla eşleşmezsek döndürür . Desene uyulmaması, Y'nin boş olamayacağı için X'in boş olması gerektiği anlamına gelir .0XY

Bu algoritma sipariş göstergesine sahiptir .Ö(|X|+|Y|)

Haskell , 34 bayt

İşte zamanında bunu nasıl yaparım :Ö(|X|x|Y|)

x#y=sum[minimum$abs.(z-)<$>y|z<-x]

Çevrimiçi deneyin!


İki tamsayı eklemenin sabit zaman aldığını varsayabileceğimiz sorusunda açıklığa kavuştum.
Anush

2

Python 2 , 124120 bayt

X,Y=input()
i=j=s=0
while i<len(X):
 v=abs(Y[j]-X[i])
 if j+1<len(Y)and v>=abs(Y[j+1]-X[i]):j+=1
 else:s+=v;i+=1
print s

Çevrimiçi deneyin!

Fonksiyona karşı programa geçerek 4 bayt kaydedildi.

Her iki liste de sıralandığından, zaman karmaşıklığı kısıtlamasını karşılamak mümkündür. Döngünün her seferinde ya iartmış ya jda artmış olduğuna dikkat edin. Böylece döngü çoğu len(X)+len(Y)zaman yürütülür .


İki tamsayı eklemenin sabit zaman alacağını varsayabileceğimiz sorusunda açıklığa kavuştum.
Anush

1

C (gcc), 82 bayt

n;f(x,y,a,b)int*x,*y;{for(n=0;a;)--b&&*x*2-*y>y[1]?++y:(++b,--a,n+=abs(*x++-*y));}

Bu, girdiyi iki tamsayı dizisi ve uzunlukları olarak alır (çünkü C'nin aksi takdirde uzunluklarını almanın bir yolu yoktur). Bunun içinde çalıştığı gösterilebilir, O(a+b)çünkü döngünün her yinelemesinde ya ada bazalır, bu da aerişildiğinde sona erer0 (ve başağıda indirildiği edilemez 0).

Çevrimiçi deneyin!

n;                     // define sum as an integer
f(x,y,a,b)             // function taking two arrays and two lengths
int*x,*y;              // use k&r style definitions to shorten function declaration
{
 for(n=0;              // initialize sum to 0
 a;)                   // keep looping until x (the first array) runs out
                       // we'll decrement a/b every time we increment x/y respectively
 --b&&                 // if y has ≥1 elements left (b>1, but decrements in-place)...
 *x*2-*y>y[1]?         // ... and x - y > [next y] - x, but rearranged for brevity...
 ++y:                  // increment y (we already decremented b earlier);
 (++b,                 // otherwise, undo the in-place decrement of b from before...
 --a,n+=abs(*x++-*y))  // decrement a instead, add |x-y| to n, and then increment x
;}

Bazı notlar:

  • Dizileri endekslemek yerine, işaretçileri artırmak ve kayıttan çıkarma doğrudan buna değecek kadar bayt kazandırır ( *xvs x[a]ve y[1]vs y[b+1]).

  • Durum dolambaçlı bir şekilde --b&&denetler b>1- eğer öyleyse b, 1sıfır olarak değerlendirilir. Bu bdeğiştiğinden, üçlünün ilk dalında (ilerleyen y) değiştirmemiz gerekmez, ancak ikincisinde (bu ilerleyen x) geri değiştirmemiz gerekir .

  • İfadeye returngerek yok , çünkü kara büyü. ( Bence değerlendirilecek son ifade her zaman n+=...dönüş değerleri için kullanılanla aynı kaydı kullanan ifade olacaktır .)


0

Ruby, 88 bayt

->(p,q){a=q.each_cons(2).map{|a|a.sum/a.size}
x=a[0]
p.sum{|n|x=a.pop if n>x
(n-x).abs}}

Çevrimiçi deneyin!

Ayrıca, eğlence için, karmaşıklık kısıtlamalarını tam olarak karşılamayan daha kısa bir anonim işlev:

->(a,b){a.map{|x|x-b.min_by{|y|(x-y).abs}}.sum}

Bu kodun nasıl çalıştığını basit bir şekilde açıklayabilir misiniz? Doğrusal zamanda çalışıp çalışmadığını söyleyemem.
Anush

2
Bu, sorudaki ilk test senaryosunun yanı sıra gibi girişlerde başarısız olur [5, 6], [0, 1, 5].
Kapı Tokmağı

0

JavaScript (Node.js) , 80 bayt

x=>g=(y,i=0,j=0,v=x[i],d=v-y[j],t=d>y[j+1]-v)=>1/v?g(y,i+!t,j+t)+!t*(d>0?d:-d):0
  • O (| X | + | Y |) içinde çalışır: Her özyineleme O (1) 'de çalışır ve özyinelemeli | X | + | Y | zamanlar.
    • x, yiçeriği kopyalamayan referansla iletilir
  • 1/veğer falsy olduğunu x[i]aksi aralık, truthy dışındaysa
  • t-> d>y[j+1]-v-> v+v>y[j]+y[j+1]aşağıdaki koşullar karşılandığı sürece yanlıştır. Ve hangi araçlar y[j]için sayı en yakın vyery
    • vküçüktür (y[j]+y[j+1])/2veya
    • y[j+1]aralığın dışında, bu da dönüşüme NaNve NaNverimle karşılaştırılacakfalse
      • bu yüzden >1 byte daha tasarruf etmek için tabelayı çeviremiyoruz
  • tBir boolean değer her zaman olduğunu ve *dönüştürmek 0/ ' 1hesaplamadan önce

Çevrimiçi deneyin!


0

Mathematica, 40 bayt

x = {1, 5, 9};
y = {3, 4, 7};

Norm[Flatten[Nearest[y] /@ x] - x]

Girişlerle birlikte tam bir program oluşturmanız gerekiyorsa:

f[x_,y_]:= Norm[Flatten[Nearest[y] /@ x] - x]

İşte 1.000.000 puana kadar (her 10.000'de bir örneklenmiş) zamanlama y:

resim açıklamasını buraya girin

Doğrusal yakın.


1
Girişiniz önceden var olan değişkenler olarak alındığı için bu cevap bir kod pasajıdır. Bir alt rutin veya tam bir program olarak yeniden biçimlendirmelisiniz.
Ad Hoc Garf Hunter

Bunun doğrusal zamanda da çalıştığından şüpheliyim, neden olması gerektiğine dair bir gerekçeniz var mı? Mathematica, yapılarının karmaşıklığında oldukça opak olma eğilimindedir.
Ad Hoc Garf Hunter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.