本文按照牛客网的顺序, 牛客网剑指 offer 刷题网址: https://www.nowcoder.com/ta/coding-interviews
本文涉及的题目:
1 用两个栈实现队列
2 旋转数组中的最小数字
3 斐波那契数列
4 跳台阶
5 变态跳台阶
6 矩形覆盖
1 用两个栈实现队列
问题描述
用两个栈来实现一个队列, 完成队列的 Push 和 Pop 操作 队列中的元素为 int 类型
思路解析
定义两个 stack, 分别是 stack1 和 stack2, 队列的 push 和 pop 是在两侧的, push 操作很简单, 只需要在 stack1 上操作, 而 pop 操作时, 先将 stack1 的所有元素 push 到 stack2 中, 然后 stack2 的 pop 返回的元素即为目标元素, 然后把 stack2 中的所有元素再 push 到 stack1 中
代码实现
- java
- import java.util.Stack;
- public class Solution {Stack < Integer> stack1 = new Stack < Integer > ();
- Stack < Integer > stack2 = new Stack < Integer > ();
- public void push(int node) {
- stack1.push(node);
- }
- public int pop() {
- int temp;
- while (!stack1.empty()) {
- temp = stack1.pop();
- stack2.push(temp);
- }
- int res = stack2.pop();
- while (!stack2.empty()) {
- temp = stack2.pop();
- stack1.push(temp);
- }
- return res;
- }
- }
- python
- class Solution:
- def __init__(self):
- self.stack1 = []
- self.stack2 = []
- def push(self, node):
- # write code here
- self.stack1.append(node)
- def pop(self):
- # return xx
- if not self.stack1:
- return None
- while self.stack1:
- self.stack2.append(self.stack1.pop())
- res = self.stack2.pop()
- while self.stack2:
- self.stack1.append(self.stack2.pop())
- return res
2 旋转数组中的最小数字
问题描述
把一个数组最开始的若干个元素搬到数组的末尾, 我们称之为数组的旋转 输入一个非递减排序的数组的一个旋转, 输出旋转数组的最小元素 例如数组 {3,4,5,1,2} 为{1,2,3,4,5}的一个旋转, 该数组的最小值为 1 NOTE: 给出的所有元素都大于 0, 若数组大小为 0, 请返回 0
思路解析
从头到尾两两相邻元素进行比较进行, 如果前面一个元素大于后面一个元素, 则返回后面一个元素如果从头到尾都没有满足条件的元素, 则返回第一个元素
代码实现
- java
- import java.util.ArrayList;
- public class Solution {
- public int minNumberInRotateArray(int[] array) {
- if (array.length == 0) {
- return 0;
- }
- for (int i = 0; i < array.length - 1; i++) {
- if (array[i] > array[i + 1]) {
- return array[i + 1];
- }
- }
- return array[0];
- }
- }
- python
- class Solution:
- def minNumberInRotateArray(self, rotateArray):
- # write code here
- if not rotateArray:
- return 0
- for i in range(len(rotateArray)-1):
- if rotateArray[i] > rotateArray[i+1]:
- return rotateArray[i+1]
- return rotateArray[0]
3 斐波那契数列
问题描述
大家都知道斐波那契数列, 现在要求输入一个整数 n, 请你输出斐波那契数列的第 n 项 n<=39
思路解析
只需要定义两个整形变量, b 表示后面的一个数字, a 表示前面的数字即可每次进行的变换是: temp = a,a=b,b=temp + b
代码实现
- java
- public class Solution {
- public int Fibonacci(int n) {
- if (n <= 0) return 0;
- int a = 1,
- b = 1;
- int temp;
- for (int i = 2; i < n; i++) {
- temp = a;
- a = b;
- b = temp + b;
- }
- return b;
- }
- }
- python
- # -*- coding:utf-8 -*-
- class Solution:
- def Fibonacci(self, n):
- # write code here
- if n<=0:
- return 0
- a = b = 1
- for i in range(2,n):
- a,b = b,a+b
- return b
4 跳台阶
问题描述
一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级求该青蛙跳上一个 n 级的台阶总共有多少种跳法
思路解析
一道典型的动态规划问题:
我们用 f(n)表示跳上 n 级台阶的跳法
可以看出, f(1)=1;f(2)=2
那么, 假设到了 n 级台阶, 那么上一步就有两种情况, 跳一步跟跳两步
如果是跳一步跳上了 n 级台阶, 那么他上一步在 n-1 级台阶, 那么有多少种方法跳到 n-1 级呢, 显然是 f(n-1), 同理, 如果跳两步, 那么上一步在 n-1 级台阶, 此时方法种数是 f(n-1), 所以总数是 f(n)=f(n-1)+f(n-2)
反向思考, 但是编写代码的时候要正向求解, 首先根据 f(1)和 f(2)计算出 f(3), 再根据 f(2)和 f(3)计算出 f(4).. 一次类推计算出第 n 项很容易理解这种思路的时间复杂度是 O(n).
代码实现
- java
- public class Solution {
- public int JumpFloor(int target) {
- if (target <= 0) return 0;
- if (target <= 2) return target;
- int a = 1,
- b = 2;
- int temp;
- for (int i = 3; i <= target; i++) {
- temp = a;
- a = b;
- b += temp;
- }
- return b;
- }
- }
- python
- # -*- coding:utf-8 -*-
- class Solution:
- def jumpFloor(self, number):
- # write code here
- if number <= 0:
- return 0
- if number == 1:
- return 1
- if number == 2:
- return 2
- res = [1,2]
- for i in range(2,number):
- res.append(res[-1] + res[-2])
- return res[-1]
5 变态跳台阶
问题描述
一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级它也可以跳上 n 级求该青蛙跳上一个 n 级的台阶总共有多少种跳法
思路解析
和普通跳台阶问题同样的思路, 反向思考, 正向写代码我们用 f(n)表示跳上 n 级台阶的跳法那么, 假设到了 n 级台阶, 我们可以一步上来, 也可以从第一级跳 n-1 级上来, 从第二级跳 n-2 级上来从 n-1 级跳一步上来, 所以 f(n) = sum(f(1) + f(2) +...+f(n-1)) + 1
代码实现
- java
- public class Solution {
- public int JumpFloorII(int target) {
- if (target <= 0) return 0;
- int sumPath = 0;
- int path = 0;
- for (int i = 0; i < target; i++) {
- path = sumPath + 1;
- sumPath = sumPath * 2 + 1;
- }
- return path;
- }
- }
- python
- # -*- coding:utf-8 -*-
- class Solution:
- def jumpFloorII(self, number):
- # write code here
- if number <= 0:
- return 0
- res = []
- sumPath = 0
- for i in range(0,number):
- res.append(sumPath + 1)
- sumPath = sumPath * 2 + 1
- return res[-1]
6 矩形覆盖
问题描述
我们可以用 2*1 的小矩形横着或者竖着去覆盖更大的矩形请问用 n 个 2*1 的小矩形无重叠地覆盖一个 2*n 的大矩形, 总共有多少种方法?
思路解析
我们用 f(n)表示覆盖 2*n 的矩形的方法数
可以看出, f(1)=1;f(2)=2
那么, 假设到了 n, 那么上一步就有两种情况, 在 n-1 的时候, 竖放一个矩形, 或着是在 n-2 时, 横放两个矩形(这里不能竖放两个矩形, 因为放一个就变成了 n-1, 那样情况就重复了), 所以总数是 f(n)=f(n-1)+f(n-2)
反向思考, 但是编写代码的时候要正向求解, 首先根据 f(1)和 f(2)计算出 f(3), 再根据 f(2)和 f(3)计算出 f(4).. 一次类推计算出第 n 项很容易理解这种思路的时间复杂度是 O(n).
代码实现
- java
- public class Solution {
- public int RectCover(int target) {
- if (target <= 0) return 0;
- if (target <= 2) return target;
- int a = 1,
- b = 2;
- int temp;
- for (int i = 3; i <= target; i++) {
- temp = a;
- a = b;
- b += temp;
- }
- return b;
- }
- }
- python
- # -*- coding:utf-8 -*-
- class Solution:
- def rectCover(self, number):
- # write code here
- if number == 0:
- return 0
- if number<=2:
- return number
- res = [1,2]
- for i in range(2,number):
- res.append(res[-1] + res[-2])
- return res[-1]
来源: http://www.jianshu.com/p/a1fd80fd251d