算法面试之剑指offer篇(一)

来源:互联网 发布:html调用java方法 编辑:程序博客网 时间:2024/06/06 03:20

(一)二维数组的查找
题目描述
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

思路分析:
可以找左下角或右上角的数字为比较值,在此假设我取左下角的数为比较值,然后通过目标数与比较值的对比做出相应的代码逻辑
即: 目标数>比较值 –>列++
目标数<比较值–>行–
目标数=比较值–>return true

代码如下:

public class Solution {    public boolean Find(int target, int [][] array) {    int i=array.length-1;    int j=0;    while((i>=0)&&(j<array[0].length)){     if(array[i][j]>target)     {             i--;     }     else if(array[i][j]<target)     {        j++ ;     }         else{       return true;        }    }          return false;     }}

(二)替换空格
题目描述
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当 字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

思路分析:
先判断传入的字符串是否为空,不为空则得到StringBuilder对象,然后通过For循环遍历传入的字符串,接着判断传入的字符是否为空格
若为空格则替换,不为空格则正常添加,最后返回String

代码如下:

public class Solution{  public String replaceSpace(StringBuffer str){    if(str==null){    return null;        }   StringBuilder sb=new StringBuilder();   for(int i=0;i<str.length();i++)   if(str.charAt(i)==' '){   sb.append('%');   sb.append('2');   sb.append('0');       }   else{   sb.append(str.charAt(i)) ;      }   return sb.toString();     }  }

(三)从尾到头打印链表

题目描述
输入一个链表,从尾到头打印链表每个节点的值。

思路分析:首先导入java.util.ArrayList类的ArrayList对象,然后定义函数传入listNode,接着判断listNode是否为空,若不为空则递归,然后添加listNode.val,最后返回ArrayList对象。

代码如下:

import java.util.ArrayList;public class Solution{ArrayList<Integer> al=new ArrayList<>(); public ArrayList<Integer> printListFromTailToHead(ListNode listNode){ if(listNode!=null){  printListFromTailToHead(listNode.next);  al.add(listNode.val); } return al;}}

(四)重建二叉树

题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路分析:
首先必须了解前序遍历的扫描顺序为根左右,而中序遍历的扫描顺序为左根右。然后定义一个私有方法进行方法的重载,判断边界条件,接着得到root对象,然后For循环进行中序遍历判断in【i】==pre【startPre】然后递归调用私有方法重建二叉树

代码如下:

/** * Definition for binary tree * public class TreeNode { *     int val; *     TreeNode left; *     TreeNode right; *     TreeNode(int x) { val = x; } * } */public class Solution {    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}    private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {        if(startPre>endPre||startIn>endIn)            return null;        TreeNode root=new TreeNode(pre[startPre]);        for(int i=startIn;i<=endIn;i++)            if(in[i]==pre[startPre]){                root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);                root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);            }        return root;    }}

(五)用两个栈实现队列

题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路分析:首先导入java.util.Stack类,然后new两个stack对象(stack1和stack2),接着定义push方法和pop方法,最后返回stack2.pop()实现队列

代码如下:

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() {        if(stack1.empty()&&stack2.empty()){        throw new RuntimeException("stack is empty!");        }        if(stack2.empty()){        while(!stack1.empty()){        stack2.push(stack1.pop());          }        }        return stack2.pop();    }}(六)旋转数组的最小数字题目描述把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。思路分析:首先对传入的数组进行判断,若数组大小为0则返回0,若数组大小为1,则数组的最小值就为数组的第一个成员即array[0],接着通过For循环对数组进行遍历,如果下标i所对应的值大于小标i+1所对应的值则交换它俩的值,直至排好序,否则如果i为数组的倒数第二个数,则说明已经排好序,最后就只要返回数组的第一个元素即可。代码如下:
 import java.util.ArrayList; public class Solution { public int minNumberInRotateArray(int [] array) {    if (array.length==0){        return 0;    }    if(array.length==1){        return array[0];    }    for(int i=0;i<array.length-1;i++){        if(array[i]>array[i+1]){            return array[i+1];        }else{         if(i==array.length-2){         return array[0];        }            }    }  return 0;}

}

(七)斐波那契数列 首先借用百度百科对斐波那契数列的描述来了解一下什么是斐波那契数列 又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:112358132134、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)题目描述大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39思路分析:从百度百科对斐波那契数列的描述,我们不难看出当n<0,则return 0,当n==1||n==2return 1,从第3个数算起就开始发生变化,接下来的值都符合F(n)=F(n-1)+F(n-2)这个规律代码如下:public class Solution {    public int Fibonacci(int n) {        int a=1,b=1,c=0;        if(n<=0){        return 0;            }else if(n==1||n==2){        return 1;            }else{        for(int i=3;i<=n;i++){        c=a+b;            b=a;            a=c;            }    }return c;  }    }(八)跳台阶题目描述一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。思路分析:首先分析数学规律,当n<=0时,则返回0,当n=1时则返回1,当n=2时返回2,当n=3时,则有11112213种跳法,此时还不好看出规律,接着看n=4,则有1111121112211225种跳法,此时不难看出规律f(1)=1,f(2)=2,f(3)=3,f(4)=5.....f(n)=f(n-1)+f(n-2),咦这个数列怎么那么熟悉,对啦这不就是我们刚学的斐波那契数列嘛代码如下: public class Solution {    public int JumpFloor(int target) {        if(target<=0){return 0;}        if(target==1){return 1;}        if(target==2){return 2;}        int one=1;        int two=2;        int result=0;        for(int i=2;i<target;i++){        result=one+two;            one=two;        two=result;            }       return result;           }}(九)变态跳台阶题目描述一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。思路分析:这一题和前一题乍一看还以为是同一题,仔细一看多了一次可以跳n级这里就不用斐波那契数列的解法,有一个更巧妙的思路,即每一个台阶都有跳与不跳两种选择,只有第n级台阶是必须跳,只有一种选择。代码如下:   public class Solution {    public int JumpFloorII(int target) {        return 1<<--target;    }}(十)矩形覆盖题目描述我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?思路分析:这题和跳台阶问题异曲同工,实为斐波那契数列代码如下:public class Solution {    public int RectCover(int target) {        if(target<=2){            return target;        }else{         return  RectCover(target-1)+RectCover(target-2);           }    }}
原创粉丝点击