Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从链表末尾删除第k个节点的内存有效方法_Java_Algorithm_Linked List_Space Complexity_Memory Efficient - Fatal编程技术网

Java 从链表末尾删除第k个节点的内存有效方法

Java 从链表末尾删除第k个节点的内存有效方法,java,algorithm,linked-list,space-complexity,memory-efficient,Java,Algorithm,Linked List,Space Complexity,Memory Efficient,这是一个已知的问题,有几个已知的解决方案,但我目前的工作是尝试找到最有效的解决方法,考虑内存使用(而不是时间复杂性) 问题:给定一个大小未知(但可能相当大)的单链接列表N,请从列表末尾删除Kth成员0首先考虑检索列表大小: public int size(Node<T> node) { int size = 0; if(node != null) { for(; node.getNext() != null; node = node.getNext())

这是一个已知的问题,有几个已知的解决方案,但我目前的工作是尝试找到最有效的解决方法,考虑内存使用(而不是时间复杂性)


问题:给定一个大小未知(但可能相当大)的单链接列表
N
,请从列表末尾删除
Kth
成员<代码>0首先考虑检索列表大小:

public int size(Node<T> node) {
   int size = 0;
   if(node != null) {
   for(; node.getNext() != null; node = node.getNext())
       size++;
   }
   return size;
}
所需额外内存:1个
int
(大小)类型的变量。 时间复杂度:O(n)

您没有解释如何存储头部节点,因此当您尝试删除第一个节点时,此实现将不起作用。修复此问题所需的修改如下:

public void removeKLast(Node<T> node, int size, int k) {
    if(k == size - 1) {
        node.setHead(node.getHead().getNext());
    } else {
        for(int i = 0; node = node.getNext() && i < size - k - 1; ++i) {}
        node.setNext(node.getNext().getNext());
    }
}
public void removeKLast(节点,int-size,int-k){
如果(k==大小-1){
node.setHead(node.getHead().getNext());
}否则{
对于(inti=0;node=node.getNext()&&i
开始列表遍历。在K步之后,启动第二个迭代器,然后并行运行。当第一个迭代器到达末尾时,第二个迭代器位于要删除的节点上


这种方法不能改变O(n)复杂度并执行大约2n(2n-k)步操作,但排除了查找结束和删除之间的“延迟”

如果事先有办法获得长度,则可以从头开始只在内存中存储第一个(len-k)元素..如果没有关于列表的进一步信息,例如,它的大小,你没有别的办法,只能完全遍历列表
O(N)
空间复杂度与您得到的一样好。“在内存中最多使用K个基元int”-
int
s代表什么?它们应该如何帮助引用要删除的对象(
节点
)?为什么不先找到大小,然后再从头开始查看列表,直到到达所需的元素?您将具有O(1)空间复杂度(您需要存储的只是列表的大小)和O(N)时间复杂度(最多2N)。如果我们讨论的是最大RAM使用率,您可以从外部存储延迟加载节点,将最后K个节点加载到RAM中。一旦到达列表的末尾,您将在RAM中拥有列表的最后K个节点,并且可以从列表中删除第一个节点。这实际上与Bernat的解决方案相同,唯一的区别是操作顺序。当然,没有办法减少操作数。但即时收益可能是有用的
public int removeKLast(Node<T> node, int size, int k) {
    for(int i = 0; node = node.getNext() && i < size - k - 1; ++i) {}
    node.setNext(node.getNext().getNext());
}
public void removeKLast(Node<T> node, int size, int k) {
    if(k == size - 1) {
        node.setHead(node.getHead().getNext());
    } else {
        for(int i = 0; node = node.getNext() && i < size - k - 1; ++i) {}
        node.setNext(node.getNext().getNext());
    }
}