Credo di poterlo fare O (n log n).
In primo luogo, ordinare l'array B
, applicando la stessa permutazione all'array A
(e ricordando la permutazione). Questa è la parte O (n log n). Dato che sommiamo tutto il i, l'applicazione della stessa permutazione agli array A e B non modifica il minimo.
Con una matrice ordinata B
, il resto dell'algoritmo è in realtà O (n).
Per ogni k, definire un array C k [i] = | B [i] - B [k] |
(Nota:. Noi non realmente costruire C k ... Ci sarà solo usarlo come un concetto per facilitare ragionamento)
osservare che la quantità che stiamo cercando di ridurre al minimo (su k) è la somma di A [i] * C k [i]. Andiamo avanti e dare che un nome:
Definire: S k = Σ A [i] * C k [i]
Ora, per un particolare k, che cosa fa C k Assomiglia a?
Bene, C k [k] = 0, ovviamente.
Più interessante, dal momento che l'array B è ordinato, possiamo sbarazzarci dei segni di valore assoluto:
- C k [i] = B [k] - B [i], per 0 < = i < k
- C k [i] = 0, per i = k
- C k [i] = B [i] - B [k], k < i < n
Definiamo ancora due cose.
Definizioni: T k = Σ A [i] per 0 < = i < k
Definizioni: U k = Σ A [i] per k < i < n
(Cioè, T k è la somma dei primi elementi k-1 di A. U k è la somma di tutti tranne i primi k elementi di A.)
L'osservazione chiave: Dato S k, T k, e U k, possiamo calcolare S k + 1, T k + 1, e U k + 1 in costante tempo. Come?
T e U sono facili.
La domanda è: come arriviamo da S k a S k + 1?
Considerare cosa succede a C k quando si va a C k + 1. Semplicemente aggiungiamo B [k + 1] -B [k] a ogni elemento di C da 0 a k, e sottraiamo la stessa quantità da ogni elemento di C da k + 1 a n (provalo). Ciò significa che dobbiamo solo aggiungere T k * (B [k + 1] - B [k]) e sottrarre U k * (B [k + 1] - B [k]) per ottenere da S k a S k + 1.
Algebricamente ... I primi k termini di S k sono solo la somma da 0 a k-1 di A [i] * (B [k] - B [i]).
I primi k termini di S k + 1 sono la somma da 0 a k-1 di A [i] * (B [k + 1] - B [i])
La differenza tra questa è la somma, da 0 a k-1, di (A [i] * (B [k + 1] - B [i]) - (A [i] * (B [k] - B [i]) Calcola i termini A [i] e cancella i termini B [i] per ottenere la somma da 0 a k-1 di A [i] * (B [k + 1] - B [k]), che è solo T k * (B [k + 1] - B [k]).
Analogamente per gli ultimi termini n-k-1 di S k.
Poiché possiamo calcolare S , T , e U in tempo lineare, e si può passare da S k a S k + 1 in tempo costante, possiamo calcolare tutti gli S k in tempo lineare. Quindi, ricordati il più piccolo e hai finito.
Utilizzare l'inverso della permutazione di ordinamento per ottenere lo k
per gli array originali.
@Dukeline: Presumo che intendesse solo un valore assoluto. – Nemo