Java教程

【算法题之剑指Offer】思路与分析:斐波那契数列、用两个栈实现队列

本文主要是介绍【算法题之剑指Offer】思路与分析:斐波那契数列、用两个栈实现队列,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JZ7 斐波那契数列

(入门)

题目

描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。 n≤39

示例
输入:
4
返回值:
3

思路

完成此题需要先了解斐波那契数列,斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用。

而此题要求我们实现一个求斐波那契数列第 n 项对应值(下标从0开始)的方法,我们首先要注意参数 n 的取值,即函数体中首先应该判断 n 的范围是否越界,题目中说的很清楚,n <= 39,下标从0开始,因此隐含 n >= 0 的条件,即 n 越界的条件是 n < 0 || n > 39 ,之后我们建立一个 40 容量的 int 数组 F,因为 F[0],F[1]为已知条件,那么 i 应从 2 开始,用打点的思路先将此数组按 F[i] = F[i - 1] + F[i - 2] 填充完整,之后只需返回参数 n 对应的 F[n] 即可。我们在最后测试时,也要记得保持一个好的习惯,在包含区间临界值的情况下,多测几组数据

实现

class Solution1 {
    public static int Fibonacci(int n) {
        if (n < 0 || n > 39) {
            return -1;
        }
        int[] F = new int[40];
        F[0] = 0;
        F[1] = 1;
        for (int i = 2; i < 40; i++) {
            F[i] = F[i - 1] + F[i - 2];
        }
        return F[n];
    }
}

public class JZ7斐波那契数列 {
    public static void main(String[] args) {
        System.out.println(Solution1.Fibonacci(0));
        System.out.println(Solution1.Fibonacci(1));
        System.out.println(Solution1.Fibonacci(2));
        System.out.println(Solution1.Fibonacci(3));
        System.out.println(Solution1.Fibonacci(4));
        System.out.println(Solution1.Fibonacci(39));
        System.out.println(Solution1.Fibonacci(40));
    }
}

在这里插入图片描述

JZ5 用两个栈实现队列

(简单)

题目

描述
用两个栈来实现一个队列,分别完成在队列尾部插入整数(push)和在队列头部删除整数(pop)的功能。 队列中的元素为int类型。保证操作合法,即保证pop操作时队列内已有元素。

例子:
输入:
[“PSH1”,“PSH2”,“POP”,“POP”]
返回:
1,2
解析:
“PSH1”:代表将1插入队列尾部
“PSH2”:代表将2插入队列尾部
"POP“:代表删除一个元素,先进先出=>返回1
"POP“:代表删除一个元素,先进先出=>返回2

示例
输入:
[“PSH1”,“PSH2”,“POP”,“POP”]
返回值:
1,2

思路

由于本题的代码模板,给出的是用 Java 集合框架中的 Stack 类来做栈的数据结构,因此我们有了现成的 push() 和 pop() 方法,而本题让实现的,是两个 Stack 对象所组成的队列的 push() 和 pop() 方法,这是我们首先要区分清楚的。

另外,在本题中,我们应该只考虑 Stack 对象的入栈、出栈和求尺寸的方法,而不应考虑其额外方法,因为本题考的意图是对于数据结构中栈和队列性质的理解,而不是对 Java 集合类中的方法熟练使用的程度,因此我们做题既需要考虑出题人的意图,也需要有相应的基础知识。

想清楚前面的问题后,我们之后在想解题思路时就可以游刃有余了,用两个栈实现一个队列的效果,无非就是将两个先进后出的数据结构组合成一个先进先出的数据结构,队列的入队与栈的入栈,我们可以等同成一种效果相同的操作,直接 push 即可,我们也不用考虑容量满的问题,因为本题中是 Stack 做数据容器,因此,我们由此就可以联想到,我们可以将 stack1 作为最终队列的数据容器,而在出队列操作时,借助另一个栈来实现上方 n - 1 个数据的暂时存储

因此本题最终的思路就是,一个主栈,一个辅助栈,最终队列的入队操作对应主栈的入栈操作,最终队列的出队操作对应主栈与辅助栈的协调工作实现。

入队思路:
在这里插入图片描述
出队思路:(补充,最终还需将 stack2 中的元素出栈,并入栈到 stack1 中,按原始顺序即可,因为这些数据本身也是从 stack1 中入栈到 stack2 中的)
在这里插入图片描述

实现

class Solution2 {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {
        stack1.push(node);
    }

    public int pop() {
        if (stack1.size() == 0) {
            return -1;
        }
        int len1 = stack1.size();
        for (int i = 0; i < len1 - 1; i++) {
            stack2.push(stack1.pop());
        }
        int popNum = stack1.pop();
        for (int i = 0; i < len1 - 1; i++) {
            stack1.push(stack2.pop());
        }
        return popNum;
    }
}

public class JZ5用两个栈实现队列 {
    public static void main(String[] args) {
        int n1 = 1;
        int n2 = 2;
        int n3 = 3;
        Solution2 solution2 = new Solution2();
        solution2.push(n1);
        solution2.push(n2);
        solution2.push(n3);
        System.out.println("solution2.pop() = " + solution2.pop());
        System.out.println("solution2.pop() = " + solution2.pop());
        System.out.println("solution2.pop() = " + solution2.pop());
        System.out.println("solution2.pop() = " + solution2.pop());
    }
}

在这里插入图片描述

这篇关于【算法题之剑指Offer】思路与分析:斐波那契数列、用两个栈实现队列的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!