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.