我需要在数组中添加一个元素,只要它在Javascript中不存在。基本上我将数组视为一组。
我需要将数据存储在数组中,否则我只使用一个可以用作集合的对象。
我写了下面的数组原型,想听听是否有人知道更好的方法。这是一个O(n)插入。我希望做O(ln(n))插入,但是,我没有看到 easy 方法将元素插入到排序数组中。对于我的应用程序,数组长度将非常小,但我仍然更喜欢符合公认规则以获得良好算法效率的东西:
Array.prototype.push_if_not_duplicate = function(new_element){
for( var i=0; i<this.length; i++ ){
// Don't add if element is already found
if( this[i] == new_element ){
return this.length;
}
}
// add new element
return this.push(new_element);
}
答案 0 :(得分:4)
如果我理解正确,你已经有一个排序数组(如果你没有排序数组,那么你可以使用Array.sort方法对数据进行排序),现在你想要添加一个元素,如果它不是已存在于数组中。我在google closure library中提取了二进制插入(使用二进制搜索)方法。相关代码本身看起来像这样,它是O(log n)操作,因为二进制搜索是O(log n)。
function binaryInsert(array, value) {
var index = binarySearch(array, value);
if (index < 0) {
array.splice(-(index + 1), 0, value);
return true;
}
return false;
};
function binarySearch(arr, value) {
var left = 0; // inclusive
var right = arr.length; // exclusive
var found;
while (left < right) {
var middle = (left + right) >> 1;
var compareResult = value > arr[middle] ? 1 : value < arr[middle] ? -1 : 0;
if (compareResult > 0) {
left = middle + 1;
} else {
right = middle;
// We are looking for the lowest index so we can't return immediately.
found = !compareResult;
}
}
// left is the index if found, or the insertion point otherwise.
// ~left is a shorthand for -left - 1.
return found ? left : ~left;
};
用法是binaryInsert(数组,值)。这也保持了数组的种类。
答案 1 :(得分:1)
我之前创建了一个(简单和不完整)Set
类型:
var Set = function (hashCodeGenerator) {
this.hashCode = hashCodeGenerator;
this.set = {};
this.elements = [];
};
Set.prototype = {
add: function (element) {
var hashCode = this.hashCode(element);
if (this.set[hashCode]) return false;
this.set[hashCode] = true;
this.elements.push(element);
return true;
},
get: function (element) {
var hashCode = this.hashCode(element);
return this.set[hashCode];
},
getElements: function () { return this.elements; }
};
您只需要为对象找到一个好的hashCodeGenerator
函数。如果您的对象是基元,则此函数可以返回对象本身。然后,您可以从getElements
访问器访问数组形式的set元素。插入是O(1)。空间要求是O(2n)。
答案 2 :(得分:1)
删除了我的另一个答案,因为我错过了数组已排序的事实。
您编写的算法遍历数组中的每个元素,如果没有匹配,则在末尾添加新元素。我认为这意味着你之后正在运行另一种类型。
使用分而治之算法可以改善整个算法。选择数组中间的元素,与新元素进行比较并继续,直到找到要插入的位置。它会比你的上述算法略快,并且之后不需要排序。
如果您需要帮助制定算法,请随时提出。
答案 3 :(得分:0)
如果您的数组是二叉树,则可以通过将新元素放在末尾并将其冒泡到位来插入O(log n)。检查重复项也需要执行O(log n)。