Java 在没有额外空间的情况下,在O(n)中反转堆栈不会发生

Java 在没有额外空间的情况下,在O(n)中反转堆栈不会发生,java,algorithm,data-structures,collections,stack,Java,Algorithm,Data Structures,Collections,Stack,我正在尝试使用递归反转堆栈: 我能够以相反的顺序打印堆栈的元素。但是,如果我试图推动相反的元素,它是不起作用的 设堆栈为[0,1,2,3,4]。4是最上面的 这就是我尝试过的: private static void reverseStack(Stack<Integer> stack) { if (!stack.isEmpty()){ int n=stack.pop(); reverseStack(stack);

我正在尝试使用递归反转堆栈:

我能够以相反的顺序打印堆栈的元素。但是,如果我试图推动相反的元素,它是不起作用的

设堆栈为[0,1,2,3,4]。4是最上面的

这就是我尝试过的:

private static void reverseStack(Stack<Integer> stack) {
        if (!stack.isEmpty()){
            int n=stack.pop();
            reverseStack(stack);
            System.out.println(n);
        }
    }
这是我所期望的

如果我尝试将这些元素推回堆栈,我将得到相同的堆栈,而不会得到反转:

这是用于反转的代码:

private static void reverseStack(Stack<Integer> stack) {
        if (!stack.isEmpty()){
            int n=stack.pop();
            reverseStack(stack);
            System.out.println(n);
            stack.push(n);
        }
    }
private static void reverseStack(堆栈){
如果(!stack.isEmpty()){
int n=stack.pop();
反向堆栈(堆栈);
系统输出println(n);
堆栈推送(n);
}
}
这是从该代码中获得的分步堆栈:

private static void reverseStack(Stack<Integer> stack) {
        if (!stack.isEmpty()){
            int n=stack.pop();
            System.out.println(stack);
            reverseStack(stack);
            System.out.println(n);
            stack.push(n);
        }
    }
private static void reverseStack(堆栈){
如果(!stack.isEmpty()){
int n=stack.pop();
System.out.println(堆栈);
反向堆栈(堆栈);
系统输出println(n);
堆栈推送(n);
}
}


我们可以清楚地看到,输出堆栈与输入堆栈相同,但仍然以相反的顺序打印元素。我哪里做错了?

您必须构建一个新堆栈,以便从旧堆栈中弹出的第一个堆栈是推到新堆栈上的第一个堆栈。不会有“额外的空间”,因为每个原始项目将在2个堆栈之一。我会使用一个知道您正在构建的堆栈的帮助函数来完成这项工作。

如果在可视化递归时遇到问题,sysout(System.out.println)将不会执行,直到满足递归的退出条件,即。当堆栈为空时。 此时递归将结束,所有元素将按该顺序打印,即0,1,2,3,4 只有这样,才能按该顺序推动元素,使堆栈变成[0,1,2,3,4] 见附图,请原谅我的笔迹:)

当您点击调用的基本大小写时,您正在将该元素放回堆栈中。然后,该函数完成,然后返回到它上面的元素,并将其添加回去

First call ([0,1,2,3,4])
int n = 4
Second call ([0,1,2,3])
int n = 3
Third call ([0,1,2])
int n = 2
Fourth call ([0,1])
int n = 1
Fifth call ([0])
int n = 0
Sixth call ([])
empty is reached, return
add 0 to stack then return ([0])
add 1 to stack then return ([0,1])
add 2 to stack then return ([0,1,2])
add 3 to stack then return ([0,1,2,3])
add 4 to stack then return ([0,1,2,3,4])
这个问题可以通过使用一个循环和两个不同的堆栈以更简单的方式解决

while(!stack.isEmpty()) {
 int n = stack.pop();
 stack2.push(n);            
}

如果您正在执行递归调用以反转堆栈,那么您将使用额外的空间。(当弹出元素并将其存储以稍后添加时)

然而,如果您使用@Scott和@Berkley提到的第二堆栈方法,则不会占用额外的空间。所以这将是你问题的正确答案

while(!stack.isEmpty()) {
 reversedStack.push(stack.pop());            
}

这里有一个不同的方法。我试图使用固定的变量集(5-max,A,A1,B,B1)并重新利用这些变量,以相反的顺序重新填充堆栈

没有递归。这意味着O(n)个额外的空间

仅适用于整数

假设Stack=[1,2,-3,4],上面有4个

最大值=5

A=((((1*5)+2)*5)+3)*5)4)*5

A1=(((((0+5)*5)+5)*5)+6)*5)+5)*5

在A和A1的帮助下,您可以重新填充堆栈,但顺序相同,因此计算B和B1的顺序相反

A1和B1要记住负整数

import java.util.Stack;
//Not ideal solution. This is only because no other data structure can be used

/*
 * 1. Find Max. Any number > max can be used for max
 * 2. Find A and A1
 * 3. Find B and B1
 * 4. Fill the Stack using B and B'
 * O( 4n ) = O( n )
 */

class Stack_Reversal_Using_Recursion { 

static Stack<Integer> stack = new Stack<>(); 

public static void main(String[] args) {

    stack.push(1);
    stack.push(8);
    stack.push(-3);
    stack.push(0);
    stack.push(4);
    System.out.println(stack);  

    better_Solution();

    System.out.println("Using mathematical approch");
    System.out.println(stack);

}
private static void better_Solution() {

    int size = stack.size();

    //Finding Max
    int max = 0;
    for(int item : stack){
        if( max < Math.abs(item) )
            max = Math.abs(item);
    }
    max = max + 1;

    //Finding A and A1
    int A = 0;
    int A1 = 0;

    while( stack.size() > 0 )
    {
        int x = stack.pop();
        A += Math.abs(x);
        A *= max;

        if( x < 0 )
            A1 += (max+1);
        else
            A1 += max;
        A1 *= max;
    }
    //A and A' hold single sum total value from which using max we can find out entire stack but in same order so we find out B and B1

    int B = 0;
    int B1 = 0;

    for( int i = 0; i < size; i++)
    {
        A = A / max;
        A1 = A1/ max;

        int A_mdl = A % max;
        A -= A_mdl;

        int A1_mdl = A1 % max;
        if( A1_mdl == 0 )
            A1_mdl = max;
        else
            A1_mdl = max + 1;
        A1 -= A1_mdl;

        B += A_mdl;
        B *= max;

        B1 += A1_mdl;
        B1 *= max;

    }

    //Now that we have B and B1 in desired order let's re-populate the Stack
    for( int i = 0; i < size; i++)
    {
        B = B / max;
        B1 = B1/ max;

        int B_mdl = B % max;
        B -= B_mdl;

        int B1_mdl = B1 % max;
        if( B1_mdl != 0 )
            B_mdl = -B_mdl;
        if( B1_mdl ==0 )
            B1 -= max;
        else
            B1 -= (max+1);

        stack.push( B_mdl );

    }

}

}
这里,+max代表正整数,+(max+1)代表负整数

import java.util.Stack;
//Not ideal solution. This is only because no other data structure can be used

/*
 * 1. Find Max. Any number > max can be used for max
 * 2. Find A and A1
 * 3. Find B and B1
 * 4. Fill the Stack using B and B'
 * O( 4n ) = O( n )
 */

class Stack_Reversal_Using_Recursion { 

static Stack<Integer> stack = new Stack<>(); 

public static void main(String[] args) {

    stack.push(1);
    stack.push(8);
    stack.push(-3);
    stack.push(0);
    stack.push(4);
    System.out.println(stack);  

    better_Solution();

    System.out.println("Using mathematical approch");
    System.out.println(stack);

}
private static void better_Solution() {

    int size = stack.size();

    //Finding Max
    int max = 0;
    for(int item : stack){
        if( max < Math.abs(item) )
            max = Math.abs(item);
    }
    max = max + 1;

    //Finding A and A1
    int A = 0;
    int A1 = 0;

    while( stack.size() > 0 )
    {
        int x = stack.pop();
        A += Math.abs(x);
        A *= max;

        if( x < 0 )
            A1 += (max+1);
        else
            A1 += max;
        A1 *= max;
    }
    //A and A' hold single sum total value from which using max we can find out entire stack but in same order so we find out B and B1

    int B = 0;
    int B1 = 0;

    for( int i = 0; i < size; i++)
    {
        A = A / max;
        A1 = A1/ max;

        int A_mdl = A % max;
        A -= A_mdl;

        int A1_mdl = A1 % max;
        if( A1_mdl == 0 )
            A1_mdl = max;
        else
            A1_mdl = max + 1;
        A1 -= A1_mdl;

        B += A_mdl;
        B *= max;

        B1 += A1_mdl;
        B1 *= max;

    }

    //Now that we have B and B1 in desired order let's re-populate the Stack
    for( int i = 0; i < size; i++)
    {
        B = B / max;
        B1 = B1/ max;

        int B_mdl = B % max;
        B -= B_mdl;

        int B1_mdl = B1 % max;
        if( B1_mdl != 0 )
            B_mdl = -B_mdl;
        if( B1_mdl ==0 )
            B1 -= max;
        else
            B1 -= (max+1);

        stack.push( B_mdl );

    }

}

}
import java.util.Stack;
//这不是理想的解决方案。这只是因为不能使用其他数据结构
/*
*1.查找最大值。任何大于最大值的数字均可用于最大值
*2.找到A和A1
*3.找到B和B1
*4.使用B和B'
*O(4n)=O(n)
*/
使用递归{
静态堆栈=新堆栈();
公共静态void main(字符串[]args){
堆栈推送(1);
栈推(8);
堆栈推送(-3);
堆栈推送(0);
堆栈推送(4);
System.out.println(堆栈);
更好的解决方案();
System.out.println(“使用数学方法”);
System.out.println(堆栈);
}
私有静态void\u解决方案(){
int size=stack.size();
//寻找Max
int max=0;
for(int项:堆栈){
如果(最大值<数学绝对值(项目))
最大值=数学绝对值(项目);
}
max=max+1;
//查找A和A1
int A=0;
int A1=0;
while(stack.size()>0)
{
intx=stack.pop();
A+=数学绝对值(x);
A*=最大值;
if(x<0)
A1+=(最大值+1);
其他的
A1+=最大值;
A1*=最大值;
}
//A和A‘保持单和总值,从中使用最大值,我们可以找出整个堆栈,但顺序相同,所以我们可以找出B和B1
int B=0;
int B1=0;
对于(int i=0;i

如前所述,这种方法仅适用于整数,人们总是可以讨论如果数字变大会发生什么!在这种情况下,As和Bs可以是大整数。

在Java中,通常不会使用递归来反转设计用于支持大量元素的类似列表的数据结构

由于Java不使用尾部调用优化,这种算法可能会产生较大的堆栈,甚至堆栈溢出。而且它们可能也不会被认为是“没有额外空间”

通过两两交换元素,即第一个元素与最后一个元素、第二个元素与第二个元素,可以简单地以O(n)时间和恒定空间复杂度在循环中反转堆栈