Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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:LinkedList分块反转_Java_Algorithm - Fatal编程技术网

Java:LinkedList分块反转

Java:LinkedList分块反转,java,algorithm,Java,Algorithm,如果为您提供了一个链表的头部,并且要求您反转每个k个节点序列,那么在Java中该如何做呢?e、 例如,a->b->c->d->e->f->g->h如果k=3,则将是c->b->a->f->e->d->h->g->f 任何一般帮助或伪代码都将不胜感激!谢谢 这是相当高的级别,但我认为它会提供一些指导 我有一个助手方法,比如voidswap3(Node-first,Node-last),它在列表的任意位置获取三个元素并将它们反转。这应该不难,可以递归地完成(交换外部元素,递归内部元素,直到列表的大小

如果为您提供了一个链表的头部,并且要求您反转每个k个节点序列,那么在Java中该如何做呢?e、 例如,
a->b->c->d->e->f->g->h
如果k=3,则将是
c->b->a->f->e->d->h->g->f


任何一般帮助或伪代码都将不胜感激!谢谢

这是相当高的级别,但我认为它会提供一些指导

我有一个助手方法,比如
voidswap3(Node-first,Node-last)
,它在列表的任意位置获取三个元素并将它们反转。这应该不难,可以递归地完成(交换外部元素,递归内部元素,直到列表的大小为0或1)。现在我想起来了,如果使用递归,您可以很容易地将其概括为
swapK()


完成后,您就可以沿着链接列表遍历并调用
swapK()
每个
k
节点。如果列表的大小不能被
k
整除,您可以不交换最后一位,或者使用交换技术反转最后一个
长度%k
节点。

如果
k
预计相当小,我只会做最简单的事情:忽略它是一个链接列表的事实,并将每个子序列视为要反转的数组类型

因此,如果链接列表的节点类是
节点
,请创建一个大小为
k
节点[]
。对于每个段,将
k
节点加载到数组列表中,然后使用一个简单的
For
循环反转它们的元素。在伪代码中:

// reverse the elements within the k nodes
for i from 0 to k/2:
    nodeI = segment[i]
    nodeE = segment[segment.length-i-1]
    tmp = nodeI.elem
    nodeI.elem = nodeE.elem
    nodeE.elem = tmp
优点:非常简单,O(N)性能,利用易于识别的反转算法

缺点:需要一个
k
大小的数组(只需一次,因为每个段可以重复使用)

还请注意,这意味着每个
节点
不会在列表中移动,只有
节点
持有的对象才会移动。这意味着每个
节点
最终将持有与以前不同的项目。这可能是好的,也可能不是,取决于您的需要。

时间O(n);空间O(1)

列表反转的一个常见要求是在O(n)时间和O(1)空间中进行。这消除了递归、堆栈或临时数组(如果K==n怎么办?),等等。 因此,这里的挑战是修改就地反转算法,以考虑
K
因素。我使用
dist
表示距离,而不是
K

这里有一个简单的就地反转算法:使用三个指针原地遍历列表:
b
指向新列表的头部
c
指向未处理列表的移动头
a
以便于在
b
c
之间进行交换

 A->B->C->D->E->F->G->H->I->J->L //original
 A<-B<-C<-D    E->F->G->H->I->J->L //during processing
          ^    ^
          |    |
          b    c
 `a` is the variable that allow us to move `b` and `c` without losing either of
  the lists.

Node simpleReverse(Node n){//n is head
if(null == n || null == n.next)
   return n;
Node a=n, b=a.next, c=b.next;
a.next=null; b.next=a;
while(null != c){
   a=c;
   c=c.next;
   a.next=b;
   b=a;
}
return b;
}
例如,通过公共Lisp

(defun rev-k (k sq)
  (if (<= (length sq) k)
      (reverse sq)
      (concatenate 'list (reverse (subseq sq 0 k)) (rev-k k (subseq sq k)))))
(第k版(平方公里)

(如果(使用堆栈并递归地从列表中删除k个项目,则将它们推到堆栈中,然后将它们弹出并添加到位。不确定这是否是最佳解决方案,但堆栈提供了一种正确的反转方式。请注意,如果您没有列表,而是有队列,则此方法也有效。
只需将k个项目出列,将它们推到堆栈中,从堆栈中弹出并将它们放入队列:)

此实现使用ListIterator类:

LinkedList<T> list;
//Inside the method after the method's parameters check
ListIterator<T> it = (ListIterator<T>) list.iterator(); 
ListIterator<T> reverseIt =  (ListIterator<T>) list.listIterator(k); 

for(int i = 0; i< (int) k/2; i++ )
{
    T element  = it.next();
    it.set(reverseIt.previous());
    reverseIt.set(element);
}
LinkedList列表;
//在方法的参数检查之后在方法内部
ListIterator it=(ListIterator)list.iterator();
ListIterator reverseIt=(ListIterator)list.ListIterator(k);
对于(int i=0;i<(int)k/2;i++)
{
T元素=it.next();
it.set(reverseIt.previous());
反向集合(元素);
}

k=3将是c->b->a->f->e->d->h->g?递归使用额外的空间O(k),其中k可能是n。请参阅我的O(n)时间,O(1)空间解决方案。@kasavbere你在这里发了一点垃圾信息,imho。你发布了你的答案并解释得很好;没有必要回复几乎所有的答案只是为了指向你的答案。我们可以看到你的答案,没有这些。@yshavit,这不是我的本意。我只回复了那些不完美的帖子,指出它们的不足之处。我不喜欢告诉人们他们做错了什么,而不告诉他们“对”是什么样子;因此我指向我发布的回复。这是一个O(n)时间,O(1)空间算法。人们可以解决没有
k
(或者说
k=n
)的基本问题然后稍微修改一下,以解决
kErm的情况,当然,你也可以只交换两个节点,节点和所有节点。这就是我在观看曲棍球时得到的答案…如果k不小呢?这个问题可以在O(n)时间和O(1)内解决空间,看我的solution@kasavbere是的,当然可以。不过,你的解决方案比我的复杂一点,所以如果你知道(从函数的req来自的任何来源)k很小,我会说使用更简单的代码。但你是对的,它有局限性,这就是为什么我显式地调用它们(两次,甚至两次)。递归使用太多空间。请参阅我的解决方案递归使用太多空间。请参阅我的解决方案太多空间。请参阅我的解决方案假设第一个算法是正确的,为什么不反向使用它?
假设第一个算法是正确的
?很容易测试。使用
插入
打印,编写一个
int
链接列表类
和此
反向功能。然后在
main()中
method用
int
s从
1到x=26
或其他什么填充列表。然后对
dist
的不同值进行反向操作。至于
为什么不反向使用它呢?
不清楚你的意思。我的意思是你修改
简单的反向操作,使它从一个索引位置反向到另一个索引位置(并保留一个额外的指针)。然后使用返回的最后一个指针,使用不同的索引反复调用
simpleReverse
。类似这样的内容…节点simpleReverse(Node from,int len,Node NextFrom);这
open System.Collections.Generic
let rev_k k (list:'T list)  =
  seq {
    let stack = new Stack<'T>()
    for x in list do
      stack.Push(x)
      if stack.Count = k then
        while stack.Count > 0 do
          yield stack.Pop()
    while stack.Count > 0 do
      yield stack.Pop()
  }
  |> Seq.toList
LinkedList<T> list;
//Inside the method after the method's parameters check
ListIterator<T> it = (ListIterator<T>) list.iterator(); 
ListIterator<T> reverseIt =  (ListIterator<T>) list.listIterator(k); 

for(int i = 0; i< (int) k/2; i++ )
{
    T element  = it.next();
    it.set(reverseIt.previous());
    reverseIt.set(element);
}