Un'opzione consiste nell'ordinare i due array, quindi attraversarli entrambi, confrontando gli elementi. Se un elemento nel sub-bag candidate non viene trovato nel super-bag, il primo non è un sub-bag. L'ordinamento è generalmente O (n * log (n)) e il confronto è O (max (s, t)), dove s e t sono le dimensioni dell'array, per una complessità temporale totale di O (m * log (m)), dove m = max (s, t).
function superbag(sup, sub) {
sup.sort();
sub.sort();
var i, j;
for (i=0,j=0; i<sup.length && j<sub.length;) {
if (sup[i] < sub[j]) {
++i;
} else if (sup[i] == sub[j]) {
++i; ++j;
} else {
// sub[j] not in sup, so sub not subbag
return false;
}
}
// make sure there are no elements left in sub
return j == sub.length;
}
Se gli elementi del codice vero e proprio sono numeri interi, è possibile utilizzare un algoritmo di ordinamento per un fine particolare intero (come radix sort) per un O complessiva (max (s, t)) Tempo di complessità, ma se il i sacchi sono piccoli, il Array.sort
integrato probabilmente funzionerà più velocemente di un ordinamento di numeri interi personalizzati.
Una soluzione con una minore complessità temporale è la creazione di un tipo di borsa. I sacchetti interi sono particolarmente facili. Capovolgi gli array esistenti per i sacchi: crea un oggetto o un array con gli interi come chiavi e un conteggio delle ripetizioni per i valori. L'utilizzo di un array non spreca spazio creando come arrays are sparse in Javascript. È possibile utilizzare le operazioni della borsa per i controlli sub-bag o super-bag. Ad esempio, sottrarre il super dal sub candidato e verificare se il risultato non è vuoto.In alternativa, l'operazione contains
deve essere O (1) (o possibilmente O (log (n))), quindi eseguire il looping sul sub-bag candidate e testare se il contenimento super-bag supera il contenimento della sottocasco per ogni sottocasco l'elemento dovrebbe essere O (n) o O (n * log (n)).
Quanto segue non è stato verificato. L'implementazione di isInt
è stata lasciata come esercizio.
function IntBag(from) {
if (from instanceof IntBag) {
return from.clone();
} else if (from instanceof Array) {
for (var i=0; i < from.length) {
this.add(from[i]);
}
} else if (from) {
for (p in from) {
/* don't test from.hasOwnProperty(p); all that matters
is that p and from[p] are ints
*/
if (isInt(p) && isInt(from[p])) {
this.add(p, from[p]);
}
}
}
}
IntBag.prototype=[];
IntBag.prototype.size=0;
IntBag.prototype.clone = function() {
var clone = new IntBag();
this.each(function(i, count) {
clone.add(i, count);
});
return clone;
};
IntBag.prototype.contains = function(i) {
if (i in this) {
return this[i];
}
return 0;
};
IntBag.prototype.add = function(i, count) {
if (!count) {
count = 1;
}
if (i in this) {
this[i] += count;
} else {
this[i] = count;
}
this.size += count;
};
IntBag.prototype.remove = function(i, count) {
if (! i in this) {
return;
}
if (!count) {
count = 1;
}
this[i] -= count;
if (this[i] > 0) {
// element is still in bag
this.size -= count;
} else {
// remove element entirely
this.size -= count + this[i];
delete this[i];
}
};
IntBag.prototype.each = function(f) {
var i;
foreach (i in this) {
f(i, this[i]);
}
};
IntBag.prototype.find = function(p) {
var result = [];
var i;
foreach (i in this.elements) {
if (p(i, this[i])) {
return i;
}
}
return null;
};
IntBag.prototype.sub = function(other) {
other.each(function(i, count) {
this.remove(i, count);
});
return this;
};
IntBag.prototype.union = function(other) {
var union = this.clone();
other.each(function(i, count) {
if (union.contains(i) < count) {
union.add(i, count - union.contains(i));
}
});
return union;
};
IntBag.prototype.intersect = function(other) {
var intersection = new IntBag();
this.each(function (i, count) {
if (other.contains(i)) {
intersection.add(i, Math.min(count, other.contains(i)));
}
});
return intersection;
};
IntBag.prototype.diff = function(other) {
var mine = this.clone();
mine.sub(other);
var others = other.clone();
others.sub(this);
mine.union(others);
return mine;
};
IntBag.prototype.subbag = function(super) {
return this.size <= super.size
&& null !== this.find(
function (i, count) {
return super.contains(i) < this.contains(i);
}));
};
Vedere anche "comparing javascript arrays" per un esempio di implementazione di un insieme di oggetti, si dovrebbe mai desiderare di non consentire la ripetizione di elementi.
L'ultimo esempio deve restituire falso. Se i 2 array hanno la stessa lunghezza, non esiste un super/sottoinsieme. http://mathworld.wolfram.com/Superset.html – Bakudan
I set non possono contenere elementi duplicati, quindi il concetto di determinare quando qualcosa è un superset in queste condizioni non ha molto senso. –
L'ultimo esempio dovrebbe essere 'true', per due ragioni: (1) la ripetizione non ha importanza negli insiemi:' {1,1} = {1} '. (2) Un set è il suo sottoinsieme e superset; se i due non dovevano essere uguali, sono chiamati "sottoinsieme appropriato" e "superset appropriato". – outis