你有2个阵列
arrA是空的。
arrB充满了东西(它充满了什么并不重要,但假设它很大)。
当用户执行某项操作时,会从arrB中删除该项目,并将该项目放在arrA中。
当用户执行其他操作时,它会从arrA中提取项目并将其放入arrB中。
是否可以在循环内没有循环的情况下执行此操作?
或者把它放在计算机科学术语中:
是否可以用线性(Θ(n))时间/空间复杂度来做到这一点?
现在我的东西至少是Θ(n * k)
(其中n是arrB的长度,k是传递给applyItems的项目数):
var arrA = [], arrB = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
function addToArray(arrayToAddTo, item){
if(arrayToAddTo.indexOf(item) === -1){
arrayToAddTo.push(item);
}
}
function removeFromArray(arrayToRemoveFrom, item){
var i = arrayToRemoveFrom.length;
var temp = [];
while(i--){
if(arrayToRemoveFrom[i] !== item){
temp.push(arrayToRemoveFrom[i]);
}
}
return temp;
}
function applyItems(arrayOfItems){
var i = arrayOfItems.length;
while(i--){
var current = arrayOfItems[i]
addToArray(arrA, current);
arrB = removeFromArray(arrB, current);
}
}
applyItems([0, 5, 3]);
console.log(arrA);
console.log(arrB);
applyItems有效,但效率不高。
这可以减少时间/空间复杂度吗?
答案 0 :(得分:1)
根据我的评论:
您可以使用比手动循环更快的本机工具。 removeFromArray可以使用indexOf来获取要删除的位置,然后使用splice删除它。此外,您可以使用引用而不是每次都重新创建数组。
进行其他一些优化......
{{1}}
答案 1 :(得分:1)
现在我的东西至少是Θ(n * k)
您可以使用O(n+k)
的高效查找结构arrayOfItems
使其不需要循环,但允许您在O(1)
中确定是否应将项目交换到另一个项目中阵列。有了它,只需arrB
一次就可以了
或者,如果您对数组进行排序并使用二进制搜索进行查找,那么您将拥有O(log k * (n+k))
。但是,如果你的阵列是有限的而且非常小,这几乎不重要。
另外,您应该在indexOf
中省略addToArray
测试。似乎已确定arrA
和arrB
中都没有项(并且您的算法保持不变),因此在将项目推送到数组之前,您不必检查重复项。
答案 2 :(得分:0)
是。您可以使用splice()
。
因此,您可以removeFromArray(arrB, current)
代替arrB.splice(i, 1);
而不是1
。这将从索引i
中删除 var i = arrA.indexOf(item)
元素。
您不需要遍历每个元素以检查它是否与您想要的元素匹配 - 只需使用indexOf()
即可。所以你可以做类似
protected void CreateBatch(Func<IBatch, List<Task>> action)
{
IBatch batch = Database.CreateBatch();
List<Task> tasks = action(batch);
batch.Execute();
Task.WaitAll(tasks.ToArray());
}
protected IEnumerable<T> GetBatch<T, TRedis>(
IEnumerable<RedisKey> keys,
Func<IBatch, RedisKey, Task<TRedis>> invokeBatchOperation,
Func<TRedis, T> buildResultItem)
{
IBatch batch = Database.CreateBatch();
List<RedisKey> keyList = keys.ToList();
List<Task> tasks = new List<Task>(keyList.Count);
List<T> result = new List<T>(keyList.Count);
foreach (RedisKey key in keyList)
{
Task task = invokeBatchOperation(batch, key).ContinueWith(
t =>
{
T item = buildResultItem(t.Result);
result.Add(item);
});
tasks.Add(task);
}
batch.Execute();
Task.WaitAll(tasks.ToArray());
return result;
}