题目:
一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈,除此之外,可以申请新的变量,但不能申请额外的数据结构。如何完成排序?
方法一:
我用一个栈实现的,只有一个排序栈,和逆序一个栈思路一样,都是使用递归的方式记录局部变量,然后一个个压入栈中
getMaxElement()方法的目的是获取栈中从栈底到栈顶方法遇见的第一个最大值,然后把该元素弹出,其他栈中元素相对位置不变,把弹出的最大值作为返回值返回
pushMaxElement()方法的目的是不断获取到最大值,然后递归调用自身,然后再从最后获取到的最大值一个个压栈,最后栈中元素从大到小依次有序
package stack_queue;
import java.util.Stack;
/**
* 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
* 除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
* @author GPJ
*
*/
public class SortStackByStack0 {
Stack<Integer> s;
boolean maxFlag;//在递归执行到栈底后,返回的过程中遇到的第一个跟返回的最大值相等的元素时,把该标志置为true,同时该元素不压栈
public SortStackByStack0(){
s = new Stack<Integer>();
maxFlag = false;
}
//获取栈中最大元素,并把该元素从该栈中弹出,其他元素的相对位置不变
public Integer getMaxElement(Integer max){
if(s.isEmpty()) return max;
Integer p = s.pop();
if(p > max){
max = p;
}
Integer returnMax = getMaxElement(max);
if(!maxFlag && returnMax == p){//如果递归返回时,遇到第一个最大值时,不压栈。
maxFlag = true;//maxFlag的作用是让递归返回时第一次遇见的最大值不压栈
return returnMax;
}
s.push(p);
return returnMax;
}
public void pushMaxElement0(){
if(s.isEmpty()) return;
maxFlag = false;
int max = getMaxElement(Integer.MIN_VALUE);
/*if(s.isEmpty()){
s.push(max);
return;
}*/
pushMaxElement0();
s.push(max);
}
public static void main(String[] args) {
SortStackByStack0 sb = new SortStackByStack0();
sb.s.push(5);
sb.s.push(1);
sb.s.push(2);
sb.s.push(5);
//sb.s.push(1);
//sb.s.push(-5);
//sb.s.push(2);
//sb.s.push(4);
sb.pushMaxElement0();
System.out.println(sb.s.pop());
System.out.println(sb.s.pop());
System.out.println(sb.s.pop());
System.out.println(sb.s.pop());
}
}
方法二:
getMaxElement()方法的目的同样是获取最大值,只不过是使用两个栈实现的,不使用递归,只是使用两个栈相互之间出栈入栈,与弹出的栈进行比较,从而获取到最大值,同时保证其他的元素相对位置不变
pushMaxElement()功能跟方法一一样,同样是使用递归方式进行局部变量的保存,在递归返回时依次入栈
package stack_queue;
import java.util.Stack;
/**
* 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
* 除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
*
* @author GPJ
*
*/
public class SortStackByStack1 {
Stack<Integer> s0;
Stack<Integer> s1;
public SortStackByStack1() {
s0 = new Stack<Integer>();
s1 = new Stack<Integer>();
}
public Integer getMaxElement() {
int max = s0.pop();
if(s0.isEmpty()){return max;}
Integer pop;
while (!s0.isEmpty()) {
pop = s0.pop();
if (max > pop) {
s1.push(pop);
} else {
s1.push(max);
max = pop;
}
}
while(!s1.isEmpty()){
s0.push(s1.pop());
}
return max;
}
public void pushMaxElement(){
if(s0.isEmpty()) return;
Integer max = getMaxElement();
pushMaxElement();
s0.push(max);
}
public static void main(String[] args) {
SortStackByStack1 sb = new SortStackByStack1();
sb.s0.push(4);
sb.s0.push(2);
sb.s0.push(-5);
sb.s0.push(1);
sb.pushMaxElement();
System.out.println(sb.s0.pop());
System.out.println(sb.s0.pop());
System.out.println(sb.s0.pop());
System.out.println(sb.s0.pop());
}
}
方法三:
只使用了一个方法实现,sortStackElement()方法目的就是排序栈s中的元素,没有使用递归,只是每一次for循环都获取到一个最小值,同时使用一个count进行标志,表示下次for循环需要循环多少次,已经获取最小值并压入到栈底的元素不用进行比较排序了
package stack_queue;
import java.util.Stack;
/**
* 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
* 除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
*
* @author GPJ
*
*/
public class SortStackByStack2 {
Stack<Integer> s0;
public SortStackByStack2() {
s0 = new Stack<Integer>();
}
public void sortStackElement(Stack<Integer> s) {
int count = 0;
while(!s.isEmpty()){//计算栈中元素个数
s0.push(s.pop());
count++;
}
while(!s0.isEmpty()){//把s0中的元素压入到栈s中
s.push(s0.pop());
}
Integer min;
Integer val;
while(count != 0){
min = s.pop();
//获取最小值,栈s中的元素出栈,即把栈s中从栈顶往下的count-1个元素出栈(因为已经min=s.pop()了一个元素了),入栈到s0中
for(int i = 0; i < count - 1; i++){
val = s.pop();
if(min > val){
s0.push(min);
min = val;
}else{
s0.push(val);
}
}
s.push(min);//把最小值放到栈s的下面
while(!s0.isEmpty()){//把栈s0中的所有元素全部压入s中
s.push(s0.pop());
}
count--;
}
}
public static void main(String[] args) {
SortStackByStack2 sb = new SortStackByStack2();
Stack<Integer> s = new Stack<Integer>();
s.push(4);
s.push(2);
s.push(-5);
s.push(1);
sb.sortStackElement(s);
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
}
}
标准答案:
使用了两个栈和一个变量,把排序栈中的第一个元素压入辅助栈中,然后如果排序栈中新弹出的cur元素比辅助栈的元素大的话,就把辅助栈中的元素压回排序栈,把cur元素压入辅助栈中。不断重复此过程,辅助栈中的元素始终是从小到大排序。
最后把辅助栈中的元素依次压入排序栈中,结束。
其中用到了栈的特性,当把元素压入栈中,在次压回另一个栈,相对顺序是不变的。
package stack_queue;
import java.util.Stack;
/**
* 一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。
* 除此之外,可以申请新的变量,但不能申请额外的数据结构,如何完成排序?
* @author GPJ
*
*/
public class SortStackByStack {
public static void sortStackByStack(Stack<Integer> stack){
Stack<Integer> help = new Stack<Integer>();
while(!stack.isEmpty()){
int cur = stack.pop();
while(!help.isEmpty() && help.peek() < cur){
stack.push(help.pop());
}
help.push(cur);
}
while(!help.isEmpty()){
stack.push(help.pop());
}
}
public static void main(String[] args) {
Stack<Integer> stack = new Stack<Integer>();
stack.push(4);
stack.push(2);
stack.push(-5);
stack.push(1);
sortStackByStack(stack);
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}
我自己的实现的比较的时间复杂度无论是最好还是最坏情况都是平方级别,而标准答案的最好情况的比较的时间复杂度是线性级别,但是最坏情况是立法级别,所以标准答案适合整体有序的的情况,而且标准答案的方法的实现很好的应用了栈的特性,我的三个方法实质是一种思路,只不过把递归实现改为循环实现,本质是一样的。
注:
其中我的实现为了方便都是在类中成员变量的形式实现的,其实是应该以方法传参实现,只是把方法多加一个参数,其他的实现完全一样,没有区别。