前22道题中需要二刷的有
题目4 重建二叉树
题目6 旋转数组的最小数字
题目12 数值的整次方
题目21 栈的压入弹出序列

题目1 二维数组的查找

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

  public boolean Find(int target, int [][] array) {
        if(array==null||array.length<1||array[0].length<1)
        {
            return false;
        }        
        int startx=0;
        int starty=array.length-1;
        while(startx<array.length&&starty>-1)
        {
             if(array[startx][starty]>target)
             {
                 starty--;
             }else if(array[startx][starty]<target)
             {
                 startx++;
             }else
             {
                 return true;
             }
        }
        return false;
    }

总结:因为这儿二维数组都是有序的所以要利用这个条件

题目2 替换空格

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

 public  String replaceSpace(StringBuffer str) {
        char[] chars = str.toString().toCharArray();
        int count=0;
        for(int i=0;i<chars.length;i++)
        {
            if(chars[i]==' ')
            count++;
        }
        char[] res=new char[chars.length+count*2];//承载结果的数组,一个空格对应这个三个字符
        int index=res.length-1;
        for(int i=chars.length-1;i>=0;i--)//倒着走,并且使用一个全局的index走新的数组
        {
            if(chars[i]!=' ')
            {
                res[index--]=chars[i];
            }else
            {
                res[index--]='0';
                res[index--]='2';
                res[index--]='%';
            }
        }
        return String.valueOf(res);
    }

总结:for循环走原数组,index走新的数组

题目3 链表的逆置

 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ListNode pre=null;
        ListNode next=null;
        while(listNode!=null)
        {
            next=listNode.next;
            listNode.next=pre;
            pre=listNode;
            listNode=next;
        }
        ArrayList<Integer> list=new ArrayList<Integer>();
        while(pre!=null)
        {
            list.add(pre.val);
            pre=pre.next;
        }
        return list;
    }

总结:需要注意的点
1,需要提前定义的变量pre,next都是指向空的
2,最后返回的是pre,这个指向的是新的头,因为cur已经指向了null
3,我们使用next来保留下一个需要处理的结点
4,当前的结点的next指向pre
5,pre变成了当前的结点
6,当前结点变成了后面的结点

            next=listNode.next;//3,
            listNode.next=pre;//4,
            pre=listNode;//5,
            listNode=next;//6,

题目4 重建二叉树 (二刷)

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

public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if (pre == null || in == null) {
            return null;
        }
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < in.length; i++) {
            map.put(in[i], i);
        }
        return preIn(pre, 0, pre.length - 1, in, 0, in.length - 1, map);
    }
    public static TreeNode preIn(int[] p, int pi, int pj, int[] n, int ni, int nj,
            HashMap<Integer, Integer> map) {
        if (pi > pj) { //base case 
            return null;
        }
        TreeNode head = new TreeNode(p[pi]);
        int index = map.get(p[pi]);
        head.left = preIn(p, pi + 1, pi + index - ni, n, ni, index - 1, map);
        head.right = preIn(p, pi + index - ni + 1, pj, n, index + 1, nj, map);
        return head;
    }
}

总结:
1,需要一个map,我们从前序到中序的映射,需要通过这个map
2,这个map在递归之前将中序的内容和下标依次存入
3,base case start前序 > end中序 极端情况是只有一个数的时候
4,index是我们通过映射得到的在中序的下标,index-start中序 中序中对应的左子树

题目5 两个栈实现一个队列

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

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

    public int pop()
    {
        if(stack2.isEmpty())
        {
            while(!stack1.isEmpty())
            {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

题目6 旋转数组的最小数字 (二刷)

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

public  int minNumberInRotateArray(int [] arr) {
             int start=0;
        int end=arr.length-1;
        int mid=0;
        while(start<end)
        {   
            /*
            注意这两个情况
            */
            if(start+1==end) break;
            if(arr[start]<arr[end]) return arr[start];
            mid=(start+end)/2;
            if(arr[mid]>arr[start])
            {
                start=mid;//为什么不使用mid+1,因为mid有可能就是最后的结果
                continue;
            }
            if(arr[mid]<arr[start])
            {
                end=mid;
                continue;
            }
            //如果是其他的情况
            //start,end,min相同
            while(start<=mid)
            {
                 if(arr[start]==arr[mid])
                 {
                     start++;
                 }
                 // 3 3 4 5 3 3 3 3 3 
                 else if(arr[start]>arr[mid])
                 {
                     return arr[mid];
                 }
                 else if(arr[start]<arr[mid])
                 {
                      return arr[start];
                 }
            }
        }
        /*
            5 4 
            3 4 
        最后剩下的如果是两个
        */
        return Math.min(arr[start],arr[end]);
    }

总结:
1,最后我们剩下的是两个数字,所以需要注意的两个位置
循环条件 start<end
程序结束位置 return Math.min(arr[start],arr[end]);
2,程序最开始的 if(start+1==end) break;
3,start=mid;//为什么不使用mid+1,因为mid有可能就是最后的结果
4,特殊情况的处理,我们列举出三种情况

3 4 5 3 3 3 3 3//case 1
3 1 2 3 3 3 3 3//case 2 
3 3 3 3 3 4 5 6

情况1 2 都可以直接返回,因为我们特殊情况是while(start<=end)

题目7 斐波那契数列

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

  public int Fibonacci(int n) {
         if(n==0) return 0;
         if(n==1||n==2) return 1;
         int pre=1;
         int prepre=1; 
         int cur=0;  
         for(int i=3;i<=n;i++)
         {
             cur=pre+prepre;
             prepre=pre;
             pre=cur;
         }
         return cur;
    }

题目8 跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

 public int JumpFloor(int n) {
        if(n==0) return 0;
        if(n==1||n==2) return n;
        int pre=2;
        int prepre=1;
        int cur=0;
        for(int i=3;i<=n;i++)
        {
            cur=pre+prepre;
            prepre=pre;
            pre=cur;
        }
        return cur;
    }

题目9 疯狂跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

public class Solution {
    public int JumpFloorII(int target) {
        int tmp=2;
        int res=1;
        target=target-1;
        for(;target!=0;target>>>=1)
        {
            if((target&1)!=0)
            {
                res=tmp*res;
            }
            tmp=tmp*tmp;
        }
        return res;
    }
}

总结:2^(n-1)

题目10 矩形覆盖

我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

public class Solution {
    public int RectCover(int n) {
        if(n==0) return 0;
        if(n==1||n==2) return n;
        int pre=2;
        int prepre=1;
        int cur=0;
        for(int i=3;i<=n;i++)
        {
            cur=pre+prepre;
            prepre=pre;
            pre=cur;
        }
        return cur;
    }
}

题目11 二进制中1的个数

 public int NumberOf1(int n) {
        int res=0;
        while(n!=0)
        {
            n-=n&(~n+1);//n=n&(n-1);
            res++;
        }
        return res;
    }

总结:两种写法

题目12 数值的整次方 二刷

public double Power(double base, int exponent) { 
        if(exponent==0 && base != 0)//情况1 非0数的0次方
            return 1;
        if(exponent==1)//情况2 任何数的1次方
            return base;
        if(base == 0 && exponent <= 0){//情况3 0的0次方没有意义
            throw new RuntimeException();
        }
        if(base ==0 && exponent>0){  //0的次方
            return 0;
        }
        //以上全部都是判断情况 
        int n= exponent;
        if(exponent<0){
            n = -exponent;
        }
        double  result=Power(base,n>>1);
        result*=result;
        if((n&1)==1)
            result*=base; 
        if(exponent<0)
            result=1/result;
        return result;     
  }

总结:
核心代码

 double  result=Power(base,n>>1);
        result*=result;
        if((n&1)==1)
            result*=base; 

举一个例子
2^11
11的二进制形式为1011
我们将2^*(101)B算出来,任何让它多加一个零变成1010B,也就是自己和自己相乘,然后判断当前的为是0还是1,如果是0的话,不管,如果是1的话,我们还要多乘一个base

题目13 调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

public void reOrderArray(int [] arr) {
       int index=0;
       int index2=0;
       while(index<arr.length)
       {
           /*
           index指向第一个偶数
           index2指向第一个奇数
           */
           while(index<arr.length&&(arr[index]&1)!=0)
           {
               index++;
           }
           //index 找到偶数
           //index2 找到奇数
           index2=index+1;
           while(index2<arr.length&&(arr[index2]&1)==0)
           {
               index2++;
           }
           if(index2<arr.length)
           {
               int tmp=arr[index2];
               for(int i=index2;i>index;i--)
               {
                   arr[i]=arr[i-1];
               }
               arr[index++]=tmp;
           }else
           {
               break;
           }
    }
    }

题目14 链表中倒数第k个结点

public ListNode FindKthToTail(ListNode head,int k) {
        if(head==null) return null;
        ListNode cur=head;
        int count=0;
        while(cur!=null)
        {
            cur=cur.next;
            count++;
        }
        if(count<k) return null;
        cur=head;
        while(cur!=null)
        {
            cur=cur.next;
            k--;
            count++;
        } 
        cur=head;
        for(int i=k;i!=0;i++)
        {
            cur=cur.next;
        }
        return cur;
    }

题目15 链表逆置

 public ListNode ReverseList(ListNode head) {
        ListNode next=null;
        ListNode pre=null;
        ListNode cur=head;

        while(cur!=null)
        {
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

题目16 合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

 public ListNode Merge(ListNode head1,ListNode head2) {
        if(head1==null)
        {
            return head2;
        }else if(head2==null)
        {
            return head1;
        }
        ListNode head=head1.val<head2.val?head1:head2;
        ListNode cur1=head==head1?head1:head2;
        ListNode cur2=head==head1?head2:head1;
        ListNode next=null;
        ListNode pre=null;
        while(cur1!=null&&cur2!=null)
        {
            if(cur1.val<=cur2.val)
            {
                 pre=cur1;
                 cur1=cur1.next;
            }else
            {
                 next=cur2.next;
                 pre.next=cur2;
                 cur2.next=cur1;
                 pre=cur2;
                 cur2=next;
            }
        }
        pre.next=cur1==null?cur2:cur1;
        return head;
    }

总结:我们的pre指针要时刻的指向上一次操作的结点,为了最后的连接

题目17 树的子结构

 public boolean HasSubtree(TreeNode node1,TreeNode node2) {
         if(node2==null) return false;
         return isContained(node1,node2);
    }
    public boolean isContained(TreeNode node1,TreeNode node2) {
         if (node2 == null) {
            return true;
         }
         if (node1 == null) {
            return false;
         }  
         return isCheck(node1,node2)||isContained(node1.left,node2)||isContained(node1.right,node2);
    }
    public static boolean isCheck(TreeNode node1, TreeNode node2)
    {
        if(node2==null)
        {
            return true;
        }
        if(node1==null||node1.val!=node2.val){
            return false;  
        } 
        return isCheck(node1.left,node2.left)&&isCheck(node1.right, node2.right);

    }

题目18 镜像二叉树

 public void Mirror(TreeNode root) {
        if(root==null) return ;
        TreeNode tmp=root.right;
        root.right=root.left;
        root.left=tmp;
        Mirror(root.left);
        Mirror(root.right);
    }

题目19 顺时针打印矩阵

 public  ArrayList<Integer> printMatrix(int[][] arr)
    {
        ArrayList<Integer> list=new ArrayList<>();
        int startl=0;
        int startc=0;
        int endl=arr.length-1;
        int endc=arr[0].length-1;
        while(startc<=endc&&startl<=endl)
        {
            printMatrixEdge(arr,startl++,startc++,endl--,endc--,list);
        }
        return list;
    }
    public static void printMatrixEdge(int[][] arr,int startl,int startc,int endl,int endc,ArrayList<Integer> list)
    {
        if(startl==endl)//只有一行
        {
             for(int i=startc;i<=endc;i++)
             {
                 list.add(arr[startl][i]);
             }
        }else if(startc==endc)//只有一列
        {
             for(int i=startl;i<=endl;i++)
             {
                list.add(arr[i][startc]);
             }
        }else 
        {
            int curl=startl;
            int curc=startc;
            while(curc<endc)
            {
                list.add(arr[startl][curc]);
                curc++;
            }
            while(curl<endl)
            {
                list.add(arr[curl][endc]);
                curl++;
            }
            while(curc>startc)
            {
                list.add(arr[endl][curc]);
                curc--;
            }
            while(curl>startl)
            {
                list.add(arr[curl][startc]);
                curl--;
            }
        }
    }

题目20 包含min函数的栈

   private Stack<Integer> stack=new Stack<>();
    private Stack<Integer> minStack=new Stack<>();

    public void push(int node) {
        stack.push(node);
        if(stack.size()==1)
        {
            minStack.push(node); 
        }else
        {
            int curValue=minStack.peek();   
            if(curValue>=node){
                minStack.push(node); 
            }else {
                minStack.push(curValue);
            }
        }
    }

    public void pop() {
        stack.pop();
        minStack.pop();
    }
    public int top() {
        return stack.peek();
    }

    public int min() {
        return minStack.peek(); 
    }

题目21 栈的压入弹出序列 二刷

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

  public boolean IsPopOrder(int [] lpush,int [] lpop) {
        int index=0;
        Stack<Integer> stack=new Stack<>();
        for(int i=0;i<lpush.length;i++)
        {
            stack.push(lpush[i]);
            while(!stack.isEmpty()&&stack.peek()==lpop[index])
            {
                stack.pop();
                index++;
            }
        }
        return stack.isEmpty();
    }

题目22 层次遍历

 public ArrayList<Integer> PrintFromTopToBottom(TreeNode head) {
        ArrayList<Integer> list=new ArrayList<>();
        if(head==null) return list;
        LinkedList<TreeNode> queue=new LinkedList<>();
        queue.addLast(head);
        while(!queue.isEmpty())
        {
            TreeNode node = queue.pollFirst();
            list.add(node.val);
            if(node.left!=null)
            {
                queue.addLast(node.left);
            }
            if(node.right!=null)
            {
                queue.addLast(node.right);
            }
        }
        return list;
    }