剑指offer题目记录(第一篇)

  1. 查找二维数组中的数,且数组中每一行每一列都是有序的。
    思路:从左下角开始,变成两条分叉,比当前数大就右移,小就上移。
public boolean Find(int target, int [][] array) {
       int i=0;
       int j=array.length-1;
       while(i<array[0].length&&j>=0){
         if(array[j][i]>target){
             j--;
         }else if(array[j][i]<target){
             i++;
         }else{
             return true;  
         }
       }
       return false;
   }
  1. 题目:请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy
    思路:从后像前替换,这样后面的字符只需要移动一次就可以
public class Solution {
    public String replaceSpace(StringBuffer str) {
        int newlenght=0;
        int spacenum=0;
    	//先计算出字符串空格的数量,算出替换后的字符串大小。
        for(int i=0;i<str.length();i++){
            if(str.charAt(i)==' '){
                spacenum++;
            }
        }
        //*2是因为本身就有一个空格
        int oldindex=str.length()-1;
        newlenght=str.length()+spacenum*2;
        str.setLength(newlenght);
        for(int i=newlenght-1;i>-1;i--,oldindex--){
            if(str.charAt(oldindex)==' '){
                str.setCharAt(i--,'0');
                str.setCharAt(i--,'2');
                str.setCharAt(i,'%');
            }else{
                str.setCharAt(i,str.charAt(oldindex));
            }
        }
        return str.toString();
    }
}
  1. t题目:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
    思路:递归解决
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> array=new ArrayList<Integer>();
        if(listNode==null){
            return array;
        }
        //从尾到头,直接用递归
        if(listNode.next==null){
            array.add(listNode.val);
            return array;
        }else{
            array=printListFromTailToHead(listNode.next);
            array.add(listNode.val);
            return array;
        }  
    }
  1. 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路:(大神提供的思路)递归思想,每次将左右两颗子树当成新的子树进行处理,中序的左右子树索引很好找,前序的开始结束索引通过计算中序中左右子树的大小来计算,然后递归求解,直到startPre>endPre||startIn>endIn说明子树整理完到。方法每次返回左子树活右子树的根节点

public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        return subTree(pre,in,0,pre.length-1,0,in.length);
    }
    private TreeNode subTree(int [] pre,int [] in,int startpre,int endpre,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=subTree(pre,in,startpre+1,startpre+i-startin,startin,i);
                root.right=subTree(pre,in,startpre+i-startin+1,endpre,i+1,endin);
                break;
            }
        }
        return root;
    }
}
  1. 题目:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路:注意点就是pop时一定要先注意stack2为空时再将stack1的添加进去,不然pop出来的就是最新推进去的代码。

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(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }
        
        Integer result=stack2.pop();
        return result;
    }
}
  1. 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
    思路,找出哪一个不变的变量,用减或加的方法重复使用他,就i不用多创建太多变量,节省空间了。
 int temp=0;
        int temp1=1;
        while(n-->0){
            temp1+=temp;
            temp=temp1-temp;
        }
        return temp;
  1. 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

参考链接:https://www.nowcoder.com/questionTerminal/8c82a5b80378478f9484d87d1c5f12a4
思路:
a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);

b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)

c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)

d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2

e.可以发现最终得出的是一个斐波那契数列:。

当然也可以用递归会开销很大,如果不想用递归可以看上一题。

  public int JumpFloor(int target) {
        if(target==1){
            return 1;
        }else if(target==2){
            return 2;
        }else{
            return JumpFloor(target-1)+JumpFloor(target-2);
        }
        
    }
  1. 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路:f(n)为跳法数
1)n = 1时,只有1种跳法,f(1) = 1
2) n = 2时,会有两个跳得方式,一次1阶或者2阶,这回归到了问题(1) ,f(2) = f(2-1) + f(2-2)
3)

f(n-1) = f(0) + f(1)+f(2)+f(3) + … + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + … + f(n-2)
f(n) = f(0) + f(1) + f(2) + f(3) + … + f(n-2) + f(n-1) = f(n-1) + f(n-1)
可以得出:
f(n) = 2*f(n-1),
也是一个是一个斐波那契数列

  public int JumpFloorII(int target) {
        if(target<=0){
            return 0;
        }else if(target==1){
            return 1;
        }else{
            return 2*JumpFloorII(target-1);
        }
    }
  1. 我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

思路:竖着放一块小矩形的话,剩下的摆放方法就还剩下
f(target-1),横着放的话,放了第一块的时候。**第一块下方那一块的位置也确定了 ,**所以剩下的摆放方法为f(target-2),还是斐波那契数列。

public int RectCover(int target) {
        if(target<=0){
            return 0;
        }else if(target==1){
            return 1;
        }else if(target==2){
            return 2;
        }else{
            return RectCover(target-1)+RectCover(target-2);
        }
    }
  1. 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

思路,有两种

  • 使用1右移到0来对每个位进行&运算结果不为0则判断该位是否有1.
//利用1进行右移来进行判断每一位是否为1.
        int count=0;
        int flag=1;
        while(flag!=0){
            if((n&flag)!=0){
                count++;
            }
            flag=flag<<1;
        }
        return count;

-通过(n-1)&n使n的每次移动都移动所有的1位

//最优解
       int count=0;
       while(n!=0){
           count++;
           n=(n-1)&n;
       }
       return count;
发布了36 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/s_xchenzejian/article/details/96289515