Loading

用一个栈实现另一个栈的排序 & 用栈来求解汉诺塔问题

用一个栈实现另一个栈的排序

题目:用一个栈实现另一个栈的排序
《程序员代码面试指南》第5题 P12 难度:士★☆☆☆

该题题解的主要思路是申请2个栈,要排序的栈记为stack,辅助栈记为help,stack栈pop出的元素记为cur

如果cur比help栈顶的元素小或相等,则压入help栈;否则,将help栈的元素逐一的压入stack栈,直到cur小于等于help栈顶元素,再将cur压入help栈。

一直执行以上操作,直到stack栈的全部元素都压入了help栈,最后再将help栈的所有元素全部压入stack栈,完成排序。

我自己想了半天没想出来这个完美的思路,我的思路就是2个栈互相压入,第一个栈保存每次pop出的最小值,第二个栈保存每次pop出的最大值;

执行5次,这个时候2个栈各自拥有原来一半的数据,最后再将第二个栈的数据全部压入第一个栈。

过程还是有点繁琐,涉及到:①每次pop时只能pop掉cnt-i+1(并且不超过cnt)个数据(底下的数据是已经排序号的从小到大或者从大到小的数据)

②每次pop在判断最值的时候,还得判断是否为上次的最值,是则直接丢弃,不过注意只能实现一次,不然会把其它相等的数也全部丢弃掉

③最后一步执行完,此时两个栈的栈顶是相同的,即有一个数据多余了,要把它pop并且丢弃掉

(光这么描述就感觉有多繁琐了┭┮﹏┭┮,当然我自己的思路也没必要再看,影响了正常题解的思路了)

自己的代码同样不贴了,太繁琐,以下是牛客网上的题解:

import java.util.Scanner;
import java.util.Stack;
 
public class Main {
 
    //将栈中的元素排序
    public static void sortStackByStatck(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) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Stack<Integer> stack = new Stack<Integer>();
        while (n-- > 0) {
            stack.push(sc.nextInt());
        }
        sortStackByStatck(stack);
        while (!stack.isEmpty()){
            System.out.print(stack.pop() + " ");//但是栈也变成一个空栈了
        }
 
    }
}

用栈来求解汉诺塔问题

题目:用栈来求解汉诺塔问题
《程序员代码面试指南》第6题 P13 难度:校★★★☆

该题虽然是校级难度,但是因为本科刘新华老师(膜拜)讲过汉诺塔问题,核心是使用递归来实现的。因此,本题虽是变种,但还是想了一会就想出来了。

该题在原来汉诺塔问题的基础上,加了限制条件:不能从最左端直接移动到最右端,必须先经过中间。从右到左亦是如此。

在看了书上的题解后,原来这个题目是有两种解法的,我也只想到了第一种,并且忽视了题目。第二种如题目所说,就是用来解决的。

由于牛客网上没有和书上相同的题解,这里放上自己的代码(除了繁琐点,核心思路是一样的):

import java.util.*;

public class Main {
    private static StringBuilder sb = new StringBuilder();
    private static Integer total = 0;
    
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        Integer cnt = Integer.parseInt(scan.nextLine());
        leftToRight(cnt);
        sb.append("It will move " + total + " steps.");
        System.out.println(sb);
    }
    public static void leftToRight(Integer n) {
        if(n > 1) {
            leftToMid(n-1);
            midToRight(n-1);
        }
        sb.append("Move " + n + " from left to mid\n");
        total++;
        if(n > 1) {
            rightToMid(n-1);
            midToLeft(n-1);
        }
        sb.append("Move " + n + " from mid to right\n");
        total++;
        if(n > 1) {
            leftToMid(n-1);
            midToRight(n-1);
        }
    }
    public static void leftToMid(Integer n) {
        if(n > 1) {
            leftToMid(n-1);
            midToRight(n-1);
        }
        sb.append("Move " + n + " from left to mid\n");
        total++;
        if(n > 1) {
            rightToMid(n-1);
        }
    }
    private static void midToRight(Integer n) {
        if(n > 1) {
            midToLeft(n-1);
        }
        sb.append("Move " + n + " from mid to right\n");
        total++;
        if(n > 1) {
            leftToMid(n-1);
            midToRight(n-1);
        }
    }
    public static void rightToMid(Integer n) {
        if(n > 1) {
            rightToMid(n-1);
            midToLeft(n-1);
        }
        sb.append("Move " + n + " from right to mid\n");
        total++;
        if(n > 1) {
            leftToMid(n-1);
        }
    }
    public static void midToLeft(Integer n) {
        if(n > 1) {
            midToRight(n-1);
        }
        sb.append("Move " + n + " from mid to left\n");
        total++;
        if(n > 1) {
            rightToMid(n-1);
            midToLeft(n-1);
        }
    }
}

完美代码请参见《程序员代码面试指南》P15

(非递归待更)

posted @ 2021-10-30 15:13  幻梦翱翔  阅读(66)  评论(0)    收藏  举报