Java 如何在O(n)时间内,在给定大小的块中反转单个链接列表?

Java 如何在O(n)时间内,在给定大小的块中反转单个链接列表?,java,algorithm,list,data-structures,Java,Algorithm,List,Data Structures,我最近遇到了一个算法问题: 在k块中反转单个链接列表,使其就位。首选迭代方法。 结果列表的第一个块相对于k应该是最大的。如果列表包含n个元素,则最后一个块将满或包含n个mod k元素 我的代码如下所示 有没有不使用堆栈或额外空间的O(n)算法 public static ListNode reverse(ListNode list, int k) { Stack<ListNode> stack = new Stack<ListNode>(); int li

我最近遇到了一个算法问题:

在k块中反转单个链接列表,使其就位。首选迭代方法。 结果列表的第一个块相对于k应该是最大的。如果列表包含n个元素,则最后一个块将满或包含n个mod k元素

我的代码如下所示

有没有不使用堆栈或额外空间的O(n)算法

public static ListNode reverse(ListNode list, int k) {
    Stack<ListNode> stack = new Stack<ListNode>();
    int listLen = getLen(list);
    int firstBlockSize = listLen % k;
    ListNode start = list;
    if (firstBlockSize != 0) {
        start = getBlock(stack, start, firstBlockSize);
    }
    int numBlock = (listLen) / k;
    for (int i = 0; i < numBlock; i++) {
        start = getBlock(stack, start, k);
    }
    ListNode dummy = new ListNode(0);
    ListNode cur = dummy;
    while (!stack.empty()) {
        cur.next = stack.peek();
        cur = stack.pop();
        while (cur.next != null) {
            cur = cur.next;
        }
    }
    return dummy.next;
}

public static ListNode getBlock(Stack<ListNode> stack, ListNode start, int blockSize) {
    ListNode end = start;
    while (blockSize > 1) {
        end = end.next;
        blockSize--;
    }
    ListNode temp = end.next;
    end.next = null;
    stack.push(start);
    return temp;
}

public static int getLen(ListNode list) {
    ListNode iter = list;
    int len = 0;
    while (iter != null) {
        len++;
        iter = iter.next;
    }
    return len;
}
公共静态ListNode反向(ListNode列表,int k){
堆栈=新堆栈();
int listLen=getLen(列表);
int firstBlockSize=listLen%k;
ListNode开始=列表;
如果(firstBlockSize!=0){
开始=getBlock(堆栈、开始、firstBlockSize);
}
int numBlock=(listLen)/k;
对于(int i=0;i1){
end=end.next;
块大小--;
}
ListNode temp=end.next;
end.next=null;
堆栈推送(启动);
返回温度;
}
公共静态int getLen(列表节点列表){
ListNode iter=列表;
int len=0;
while(iter!=null){
len++;
iter=iter.next;
}
回程透镜;
}

这里有一种迭代的方法。。。你读我的

Node reverseListBlocks1(节点头,int k){
如果(head==null | | k这可以在O(n)时间内使用O(1)空间完成,如下所示:

  • 颠倒整个列表
  • 反转各个块
这两种方法都可以使用非常类似的方法来实现,并且整个过程类似于

通过使用长度变量,只反转给定的块相当容易

当我们需要从一个块移动到下一个块时,会出现复杂的情况。我实现这一点的方法是让reverse函数返回第一个和最后一个节点,并让最后一个节点指向原始链表中的下一个节点。这是必要的,因为最后一个节点的下一个指针需要更新为指向前n个节点我们的下一个反向调用返回(在调用完成之前,我们不知道它需要指向什么)

为了简单起见,我在下面的代码中使用了一个
null
start节点(否则我需要专门针对start节点,这会使代码复杂化)


.

反转单链表的最简单方法如下所示

private void reverse(Node node)
{
    Node current = Node;
    Node prev = null;
    Node next = null;

    if(node == null || node.next == null)
    {
        return node;
    }

    while(current != null)
    {
        next = current.next;
        //swap
        current.next = prev;
        prev = current;
        current = next;
    }
    node.next = current;
}

本节包含多个单链表操作

import java.util.Scanner;
import java.util.Stack;

public class AddDigitPlusLL {

    Node head = null;
    int len =0;

    static class Node {
        int data;
        Node next;

        Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    public void insertFirst(int data) {
        Node newNode = new Node(data);
        if (head != null)
            newNode.next = head;

        head = newNode;

    }

    public void insertLast(int data) {
        Node temp = head;
        Node newNode = new Node(data);
        if (temp == null)
            head = newNode;
        else {
            Node previousNode = null;
            while (temp != null) {
                previousNode = temp;
                temp = temp.next;
            }
            previousNode.next = newNode;
        }

    }

    public Long getAllElementValue() {
        Long val = 0l;
        Node temp=head;
        while(temp !=null) {
            if(val == 0)
                val=(long) temp.data;
            else
                val=val*10+temp.data;
            temp = temp.next;
        }

        System.out.println("value is :" +  val);
        return val;
    }

    public void print(String printType) {
        System.out.println("----------- :"+ printType +"----------- ");
        Node temp = head;
        while (temp != null) {
            System.out.println(temp.data + "  --> ");
            temp = temp.next;
        }
    }

    public void generateList(Long val) {
        head = null;
        while(val > 0) {
            int remaining = (int) (val % 10);
            val = val/10;
            insertFirst(remaining);

        }
    }

    public void reverseList(Long val) {
        head =null;
        while(val >0) {
            int remaining = (int) (val % 10);
            val = val/10;
            insertLast(remaining);
        }
    }

    public void lengthRecursive(Node temp) {
        if(temp != null) {
            len++;
        lengthRecursive(temp.next);

        }
    }

    public void reverseUsingStack(Node temp) {
        Stack<Integer> stack = new Stack<Integer>();
        while(temp != null) {
            stack.push(temp.data);
            temp = temp.next;
        }

        head = null;
        while(!stack.isEmpty()) {
            int val = stack.peek();
            insertLast(val);
            stack.pop();
        }

        print(" Reverse Using Stack");
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner s = new Scanner(System.in);
        AddDigitPlusLL sll = new AddDigitPlusLL();
        sll.insertFirst(5);
        sll.insertFirst(9);
        sll.insertLast(8);
        sll.print("List Iterate");
        Long val = sll.getAllElementValue();
        System.out.println("Enter the digit to add");
        Long finalVal = val +s.nextInt();
        s.close();
        sll.generateList(finalVal);
        sll.print("Add int with List Value");
        sll.reverseList(finalVal);
        sll.print("Reverse the List");
        sll.lengthRecursive(sll.head);
        System.out.println("Length with Recursive  :"+ sll.len);
        sll.print("Before call stack reverse method");
        sll.reverseUsingStack(sll.head);
    }
}
import java.util.Scanner;
导入java.util.Stack;
公共类AddDigitPlusLL{
节点头=空;
int len=0;
静态类节点{
int数据;
节点下一步;
节点(int数据){
这个数据=数据;
this.next=null;
}
}
公共void insertFirst(int数据){
Node newNode=新节点(数据);
if(head!=null)
newNode.next=头部;
头=新节点;
}
公共void insertLast(int数据){
节点温度=头;
Node newNode=新节点(数据);
if(temp==null)
头=新节点;
否则{
节点previousNode=null;
while(temp!=null){
前一个节点=温度;
温度=下一个温度;
}
previousNode.next=新节点;
}
}
公共长GetAllegementValue(){
长val=0l;
节点温度=头;
while(temp!=null){
如果(val==0)
val=(长)温度数据;
其他的
val=val*10+温度数据;
温度=下一个温度;
}
System.out.println(“值为:”+val);
返回val;
}
公共作废打印(字符串打印类型){
System.out.println(“------------:”+printType+“------------”;
节点温度=头;
while(temp!=null){
System.out.println(temp.data+“-->”);
温度=下一个温度;
}
}
公共无效生成列表(长val){
head=null;
while(val>0){
剩余整数=(整数)(val%10);
val=val/10;
插入第一个(剩余);
}
}
公共无效反向列表(长val){
head=null;
while(val>0){
剩余整数=(整数)(val%10);
val=val/10;
最后一次插入(剩余);
}
}
公共无效长度递归(节点温度){
如果(温度!=null){
len++;
长度递归(下一个温度);
}
}
公共void reverseUsingStack(节点温度){
堆栈=新堆栈();
while(temp!=null){
堆栈推送(温度数据);
温度=下一个温度;
}
head=null;
而(!stack.isEmpty()){
int val=stack.peek();
插入体(val);
stack.pop();
}
打印(“使用堆栈反转”);
}
公共静态void main(字符串[]args){
//TODO自动生成的方法存根
扫描仪s=新的扫描仪(System.in);
AddDigitPluslSLL=新的AddDigitPlusLL();
sll.insertFirst(5);
sll.insertFirst(9);
sll.insertLast(8);
sll.打印(“列表迭代”);
Long val=sll.getAllegementValue();
System.out.println(“输入要添加的数字”);
Long finalVal=val+s.nextInt();
s、 close();
sll.生成专家(最终);
sll.print(“用列表值添加int”);
sll.反向列表(最终);
sll.打印(“颠倒列表”);
sll.长度递归(sll.头部);
class Test
{
   static class Node<T>
   {
      Node next;
      T data;
      Node(T data) { this.data = data; }
      @Override
      public String toString() { return data.toString(); }
   }

   // reverses a linked-list starting at 'start', ending at min(end, len-th element)
   // returns {first element, last element} with (last element).next = (len+1)-th element
   static <T> Node<T>[] reverse(Node<T> start, int len)
   {
      Node<T> current = start;
      Node<T> prev = null;
      while (current != null && len > 0)
      {
         Node<T> temp = current.next;
         current.next = prev;
         prev = current;
         current = temp;
         len--;
      }
      start.next = current;
      return new Node[]{prev, start};
   }

   static <T> void reverseByBlock(Node<T> start, int k)
   {
      // reverse the complete list
      start.next = reverse(start.next, Integer.MAX_VALUE)[0];
      // reverse the individual blocks
      Node<T>[] output;
      Node<T> current = start;
      while (current.next != null)
      {
         output = reverse(current.next, k);
         current.next = output[0];
         current = output[1];
      }
   }

   public static void main(String[] args)
   {
      //Scanner scanner = new Scanner(System.in);
      Scanner scanner = new Scanner("3 9 1 2 3 4 5 6 7 8 9\n" +
                                    "2 9 1 2 3 4 5 6 7 8 9");
      while (scanner.hasNextInt())
      {
         int k = scanner.nextInt();
         // read the linked-list from console
         Node<Integer> start = new Node<>(null);
         Node<Integer> current = start;
         int n = scanner.nextInt();
         System.out.print("Input: ");
         for (int i = 1; i <= n; i++)
         {
            current.next = new Node<>(scanner.nextInt());
            current = current.next;
            System.out.print(current.data + " ");
         }
         System.out.println("| k = " + k);
         // reverse the list
         reverseByBlock(start, k);
         // display the list
         System.out.print("Result: ");
         for (Node<Integer> node = start.next; node != null; node = node.next)
            System.out.print(node + " ");
         System.out.println();
         System.out.println();
      }
   }
}
Input: 1 2 3 4 5 6 7 8 9 | k = 3
Result: 7 8 9 4 5 6 1 2 3 

Input: 1 2 3 4 5 6 7 8 9 | k = 2
Result: 8 9 6 7 4 5 2 3 1 
private void reverse(Node node)
{
    Node current = Node;
    Node prev = null;
    Node next = null;

    if(node == null || node.next == null)
    {
        return node;
    }

    while(current != null)
    {
        next = current.next;
        //swap
        current.next = prev;
        prev = current;
        current = next;
    }
    node.next = current;
}
import java.util.Scanner;
import java.util.Stack;

public class AddDigitPlusLL {

    Node head = null;
    int len =0;

    static class Node {
        int data;
        Node next;

        Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    public void insertFirst(int data) {
        Node newNode = new Node(data);
        if (head != null)
            newNode.next = head;

        head = newNode;

    }

    public void insertLast(int data) {
        Node temp = head;
        Node newNode = new Node(data);
        if (temp == null)
            head = newNode;
        else {
            Node previousNode = null;
            while (temp != null) {
                previousNode = temp;
                temp = temp.next;
            }
            previousNode.next = newNode;
        }

    }

    public Long getAllElementValue() {
        Long val = 0l;
        Node temp=head;
        while(temp !=null) {
            if(val == 0)
                val=(long) temp.data;
            else
                val=val*10+temp.data;
            temp = temp.next;
        }

        System.out.println("value is :" +  val);
        return val;
    }

    public void print(String printType) {
        System.out.println("----------- :"+ printType +"----------- ");
        Node temp = head;
        while (temp != null) {
            System.out.println(temp.data + "  --> ");
            temp = temp.next;
        }
    }

    public void generateList(Long val) {
        head = null;
        while(val > 0) {
            int remaining = (int) (val % 10);
            val = val/10;
            insertFirst(remaining);

        }
    }

    public void reverseList(Long val) {
        head =null;
        while(val >0) {
            int remaining = (int) (val % 10);
            val = val/10;
            insertLast(remaining);
        }
    }

    public void lengthRecursive(Node temp) {
        if(temp != null) {
            len++;
        lengthRecursive(temp.next);

        }
    }

    public void reverseUsingStack(Node temp) {
        Stack<Integer> stack = new Stack<Integer>();
        while(temp != null) {
            stack.push(temp.data);
            temp = temp.next;
        }

        head = null;
        while(!stack.isEmpty()) {
            int val = stack.peek();
            insertLast(val);
            stack.pop();
        }

        print(" Reverse Using Stack");
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner s = new Scanner(System.in);
        AddDigitPlusLL sll = new AddDigitPlusLL();
        sll.insertFirst(5);
        sll.insertFirst(9);
        sll.insertLast(8);
        sll.print("List Iterate");
        Long val = sll.getAllElementValue();
        System.out.println("Enter the digit to add");
        Long finalVal = val +s.nextInt();
        s.close();
        sll.generateList(finalVal);
        sll.print("Add int with List Value");
        sll.reverseList(finalVal);
        sll.print("Reverse the List");
        sll.lengthRecursive(sll.head);
        System.out.println("Length with Recursive  :"+ sll.len);
        sll.print("Before call stack reverse method");
        sll.reverseUsingStack(sll.head);
    }
}