package com.overridere.onetoten;
import java.util.ArrayList;
public class Solution {
/**
* 第一题
* 在一个二维数组中,每一行都按照从左到右递增的顺序排序,
* 每一列都按照从上到下递增的顺序排序。
* 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
*/
public boolean Find(int target, int [][] array) {
int row = 0;
int col = array[0].length - 1;
while(row < array.length && col >= 0){
if(array[row][col] < target){
row ++;
}else if(array[row][col] > target){
col --;
}else{
return true;
}
}
return false;
}
/**
* 第二题
* 请实现一个函数,将一个字符串中的空格替换成“%20”。
* 例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
*/
public String replaceSpace(StringBuffer str) {
//方式一:自带替换行数
//return str.toString().replaceAll("\\s", "%20");
//方式二:自己编写替换
//想法:就跟数组替换一样,因为字符串类型的容量和字符串时间内容的长度一样,所以如果自己进行替换的话需要扩容
//需要扩容就要考虑要扩容多少,因为替换的字符串和被替换的字符串长度差为2,所以每次遇到需要替换的字符串的时候就可以将长度+2
int len = str.length();
int num = 0;
for(int i = 0; i < len; i ++){
if(str.charAt(i) == ' '){ //如果是空格的话
str.setLength(str.length()+2); //将长度加长2个,因为插入的字符串比替换的字符串长2,所以没遇到一个空格就要多两个长度
num +=2; //记录一下新增位置的数量
}
}
//带到这里新的被扩容的字符串容器弄好了,接下来就是遍历替换了
//因为扩容的位置是在后面加上的,如果从前面遍历的话,遇到一个空格将要将后面所有元素往后推,这样效率低
//从后遍历的话可以这样做,因为位置是在后面添加的,所以从后面遍历的时候就可以带着新增的位置往前遍历,遇到空格就把位置方向来进行替换
//假设数组为' who are you ',扩容之后为' who are you 'num为8,len为以前的长度13
//第一次遇到空格的时候j为len-1,num为8,变化为' who are you %20'
//第一次遇到不少空格的时候(u),变化为' who are yo u%20'
//然后继续:' who are y ou%20'--》' who are you%20'--》' who are %20you%20'
for(int j = len-1;j >= 0;j --){
if(str.charAt(j) == ' '){
num-=2;
str.setCharAt(j+num,'%');
str.setCharAt(j+num+1,'2');
str.setCharAt(j+num+2,'0');
}else
str.setCharAt(j+num, str.charAt(j));
}
return str.toString();
}
public String replaceSpace2(StringBuffer str) {
//方式三:在扩容的时候顺便插入了
for(int i = 0; i < str.length(); i ++){
if(str.charAt(i) == ' '){
str.setLength(str.length()+2);
for(int j = str.length()-1;j > i+2;j --){
str.setCharAt(j, str.charAt(j-2));
}
str.setCharAt(i,'%');
str.setCharAt(i+1,'2');
str.setCharAt(i+2,'0');
}
}
return str.toString();
}
/**
* 第三题
* 输入一个链表,从尾到头打印链表每个节点的值。{67,0,24,58}
*/
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<>();
if(listNode != null){
list = printListFromTailToHead(listNode.next);
list.add(listNode.val);
}
return list;
}
/**
* 第四题
* 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
* 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
*/
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
//前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
public TreeNode reConstructBinaryTree(int [] p,int sp,int ep,int [] in,int si,int ei) {
if(sp>ep||si>ei)
return null;
TreeNode root=new TreeNode(p[sp]);
//中序遍历得出的数组特点为:根左边的数据-根节点-根右边的数据
//前序遍历得出的数组特点为:根-根左边的数据-根右边的数据
//所以左儿子就可以在根左边的数据中找,右儿子在根右边的数据中找
// 根左边的数据 (-根节点) -根右边的数据
//(根节点-) 根左边的数据 -根右边的数据
//递归的时候就可以把根节点去掉了,找左儿子就传递两个根左边的数据,找右儿子就传递两个根右边的数据
for(int i=si;i<=ei;i++){
if(in[i]==p[sp]){//意味着遍历到了根
//前序遍历切割为:2,4,7,中序遍历切割为:4,7,2,两个数组都是根节点左边的数据
root.left=reConstructBinaryTree(p,sp+1,sp+i-si,in,si,i-1);
//前序遍历切割为:3,5,6,8,中序遍历切割为:5,3,8,6,两个数组都是根节点右边的数据
root.right=reConstructBinaryTree(p,i-si+sp+1,ep,in,i+1,ei);
}
}
return root;
}
/**
* 第五题 QueueFromTwoStack
*/
/**
* 第六题
* 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
* 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
* 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
* NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
*/
public int minNumberInRotateArray(int [] array) {
for(int i = 0; i < array.length-1; i ++){
if(array[i]>array[i+1]){
return array[i+1];
}
}
return 0;
}
/**
* 第七题
* 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39
*/
public int Fibonacci(int n) {
//方式一:
// if(n <= 0)
// return 0;
// else if(n == 1)
// return 1;
// else
// return Fibonacci(n-1) + Fibonacci(n-2);
//方式二:递归2
// return tailRecursion(n, 0, 1);
// 方式三
// int [] nums = new int[n];
// if(n <= 0){
// return 0;
// }
// for(int i = 0; i < n; i ++){
// if(i <= 1)
// nums[i] = 1;
// else
// nums[i] = nums[i-1] + nums[i-2];
// }
// return nums[nums.length - 1];
//方式四
int n1 = 0; int n2 = 1;
if(n <= 0)
return n1;
else if(n == 1)
return n2;
else{
while(n-->1){
n2 = n1 + n2;
n1 = n2 - n1;
}
}
return n2;
}
public int tailRecursion(int n, int n1, int n2){
if(n <= 0)
return 0;
else if(n == 1)
return n2;
else
return tailRecursion(--n, n2, n1+n2);
}
/**
* 第八题
* 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
*
* 其它方法可以参考上面的题目
*/
public int JumpFloor(int target) {
//也是斐波那契数列
int n1 = 0; int n2 = 1;
if(target <= 0)
return n1;
else if(target <= 2)
return target;
else{
while(target-->1){
n2 = n1 + n2;
n1 = n2 - n1;
}
}
return n1+n2;
}
/**
* 第九题
* 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
*
* 思路:当你还没跳到时候,你有n种跳法,跳1阶或者2阶。。。或者n阶,
* 当你在1阶的时候有n-1中跳法,当你在2阶的时候有n-2种跳法,当你在n-1阶时只有1中跳法
* 逆向思路:当你在n阶的时候你有可能从n-1阶跳过来的,也有可能是从n-2阶。。。。或者从1阶跳过来的,或者从0跳过来的
* 总共有n种台阶让你到达n阶,当你在n-1阶的时候总共有n-1种台阶让你到达n-1阶
* 设函数f(n)为你到达n阶所可能使用的跳法总数,如果是从n-1阶跳过来的那么就要知道到达n-1阶所可能使用的跳法总数。。。
* 所以f(n) = f(n-1)+f(n-2)+...+f(1)+f(0),f(n-1) = f(n-2)+f(n-3)...+f(1)+f(0)...
* 所以f(n) = f(n-1)+[f(n-2)+...+f(1)+f(0)] = f(n-1)+f(n-1) = 2f(n-1);
*/
public int JumpFloorII(int target) {
if(target <= 0)
return 0;
else if(target == 1)
return 1;
else{
return 2 * JumpFloorII(target - 1);
}
}
/**
* 第十题
* 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。
* 请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
*
* 思路:如果最后一个小矩形是横向放置的,那么第n-1个小矩形肯定也是横向放置的,前n-2个矩形放置方法总数需要求
* 如果最后一个小矩形是纵向放置的,则前n-1个矩形放置方法总数需要求
* 所以f(n) = f(n-1)+f(n-2) 斐波那契递归,这种递归又有好多种其它方法实现
*
*/
public int RectCover(int target) {
int n1 = 1,n2 = 2;
if(target <= 0)
return 0;
else if(target == 1)
return 1;
else if(target == 2)
return 2;
while(target-- > 2){
n2 = n1 + n2;
n1 = n2 - n1;
}
return n2;
}
}
第五题
package com.overridere.onetoten;
import java.util.Stack;
/**
* 第五题
* 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
* @author OverrideRe
*
*/
public class QueueFromTwoStack {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack2.isEmpty()){
while(stack1.size() > 0){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}