ändern Sie diese mit dynamischer Programmierung lösen können. Halten Sie eine Karte aller möglichen Teilsummen (Abbildung auf die minimale Anzahl von Änderungen, diese Summe zu erreichen), und dann aktualisieren sie eine Nummer zu einem Zeitpunkt,
Hier ist eine kurze Python Lösung:
def signs(nums):
xs = {nums[0]: 0}
for num in nums[1:]:
ys = dict()
for d, k in xs.iteritems():
for cost, n in enumerate([num, -num]):
ys[d+n] = min(ys.get(d+n, 1e100), k+cost)
xs = ys
return xs.get(0, -1)
print signs([1, 1, -4, -4, -4, -2, -2])
In Theorie hat im schlimmsten Fall exponentielle Komplexität (da sich die Anzahl der Partialsummen bei jedem Schritt verdoppeln kann). Wenn jedoch (wie hier) die gegebenen Zahlen immer (begrenzt) kleine Inte sind, dann wächst die Anzahl der Teilsummen linear, und das Programm arbeitet in O (n^2) -Zeit.
Eine etwas optimierte Version verwendet ein sortiertes Array von (Zwischensumme, Kosten) anstelle eines Diktats. Man kann Teilmengen, die zu groß oder zu klein sind, verwerfen (was es unmöglich macht, bei 0 zu enden, vorausgesetzt, dass alle verbleibenden Elemente zwischen -300 und +300 liegen). Dies läuft ungefähr doppelt so schnell ab und ist eine natürlichere Implementierung, um für eine maximale Geschwindigkeit in eine Sprache auf niedrigerer Ebene als Python zu portieren.
def merge(xs, num):
i = j = 0
ci = 0 if num >= 0 else 1
cj = 0 if num < 0 else 1
num = abs(num)
while j < len(xs):
if xs[i][0] + num < xs[j][0] - num:
yield (xs[i][0] + num, xs[i][1] + ci)
i += 1
elif xs[i][0] + num > xs[j][0] - num:
yield (xs[j][0] - num, xs[j][1] + cj)
j += 1
else:
yield (xs[i][0] + num, min(xs[i][1] + ci, xs[j][1] + cj))
i += 1
j += 1
while i < len(xs):
yield (xs[i][0] + num, xs[i][1] + ci)
i += 1
def signs2(nums):
xs = [(nums[0], 0)]
for i in xrange(1, len(nums)):
limit = (len(nums) - 1 - i) * 300
xs = [x for x in merge(xs, nums[i]) if -limit <= x[0] <= limit]
for x, c in xs:
if x == 0: return c
return -1
print signs2([1, 1, -4, -4, -4, -2, -2])
Eine Möglichkeit, den Suchbaum bei Rückzieher könnte zu beschneiden zu erkennen, dass '+ 4 - 4' gleich ist wie '- 4 + 4'. –
Ergreifen Sie die Gesamtparität, wenn es sich um einen ungeraden Druck -1 handelt. – Vesper
Nein, Zahlen sind '1 <= x <300' – user2660964