Java 如何在O(n)时间内,在给定大小的块中反转单个链接列表?
我最近遇到了一个算法问题: 在k块中反转单个链接列表,使其就位。首选迭代方法。 结果列表的第一个块相对于k应该是最大的。如果列表包含n个元素,则最后一个块将满或包含n个mod k元素 我的代码如下所示 有没有不使用堆栈或额外空间的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
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);
}
}