剑指offer-算法整理

通读了剑指offer这本书,决定把上面涉及到的算法进行整理,加深对算法的理解,并通过Java代码进行实践。待更新。。。

package com.xpn.offer;

import java.util.Stack;




/**
 * 2、实现singleton模式
 * 3、二维数组的查找,从左到右、从上到下有序 findSortedMatrix
 * 4、替换字符串的空格为“%20”,从后往前替换,提高效率replaceBlack
 * 5、从尾到头打印链表printReverseList printReverseListRec
 * 6、重建二叉树(根据前序和中序遍历的结果)
 * 7、用两个栈实现一个队列
 * 8、旋转数组的最小数字:递增排序的一个旋转数组,找出最小的元素 findMinRotatedArray
 * 9、斐波那契数列:递归实现、迭代实现(效率)DP
 * 10、二进制中1的个数 n&(n-1)将最右边一位的1置0
 * 11、数值的整数次方
 * 12、打印1到最大的n位数(大数问题,字符串模拟)、数字排列问题?
 * 13、O(1)时间删除链表结点。思路:复制数据,然后删除。尾结点单独处理(需要遍历)
 * 14、调整数组顺序,使得奇数位于偶数前面 reorderOddEven
 * 15、链表中倒数第k个结点。要点:两个指针,异常处理,鲁棒性考察
 * 16、反转链表,异常处理
 * 17、合并两个排序的链表,额外申请头结点,为空情况考虑
 * 18、判断树B是否为树A的子结构
 * 19、二叉树的镜像
 * 20、顺时针打印矩阵,从外向里顺序打印每一个数字printMatrix,找到规律和边界条件
 * 22、包含min函数的栈
 * 23、栈的压入弹出序列,序列A:压栈序列,序列B:出栈序列,判断B是否正确?isPopOrder
 * 24、从上打印二叉树:层次遍历,队列实现
 * 25、二叉搜索树树的后序遍历,判断输入的数组是否为后续二叉搜索树的遍历结果,找规律,递归实现。
 * @author xpn
 *
 */
public class Main {
    private static class TreeNode {  
        int val;  
        TreeNode left;  
        TreeNode right;  

        public TreeNode(int val) {  
            this.val = val;  
        }  
    } 
    static class Node{
        int value;
        public Node(int value) {
            this.value=value;
        }
        Node next;
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        Node n1 = new Node(1);  
        Node n2 = new Node(2);  
        Node n3 = new Node(3);  
        Node n4 = new Node(4);  
        Node n5 = new Node(5);  
        n1.next = n2;  
        n2.next = n3;  
        n3.next = n4;  
        n4.next = n5;  
       // printReverseListRec(n1);
        int mat[][]={
                {1,2,3,4},
                {5,6,7,8},
                {10,11,12,13}
        };
        printMatrix(mat,mat[0].length,mat.length);
        int[] A={1,2,3,4,5};
        int[] B={4,3,5,1,2};
System.out.println(isPopOrder(A,B));
    }
    //2.实现singleton模式
    //构造函数私有,返回实例静态
    static class Singleton{
        private  Singleton() {

        }
        private static Singleton instance=null;
        private static Object flag=1;//必须是个对象
        public  static Singleton getInstance () {
            if(instance==null){
                synchronized (flag) {
                    if(instance==null)
                        instance=new Singleton();
                }

            }
            return instance;
        }
    }

    //3、二维数组的查找,从左到右、从上到下有序 findSortedMatrix
    //思路:从右上角到左下角进行二分查找
    private static boolean findSortedMatrix(int[][] A,int num){
        if(A==null)
            return false;
        int m=A.length;//行
        int n=A[0].length;//列
        int i=0;
        int j=n-1;
        while(i<m&&j>=0){
            if(num==A[i][j]){
                return true;
            }else if(num<A[i][j]){
                j--;
            }else {
                i++;
            }
        }
        return false;
    }
    //4、替换字符串的空格为“%20”,从后往前替换,提高效率replaceBlack
    //思路:从后往前进行,此思路还适应于合并2个数组,减少移动次数。
    //5、从尾到头打印链表printReverseList printReverseListRec
    //思路:通过栈来迭代,或者使用递归

    private static void printReverseListRec(Node head){
        if(head==null)
            return;
        printReverseListRec(head.next);
        System.out.print(head.value+" ");
    }
    //6、重建二叉树(前序+中序) constructTree 递归思想解决
    /**
     * 
     * @param A 前序遍历
     * @param s1 前序遍历开始下标
     * @param e1 前序遍历开始下标
     * @param B 中序遍历
     * @param s2 中序遍历开始下标
     * @param e2 中序遍历开始下标
     * @return
     */
    private static TreeNode constructTree(int[] A,int s1,int e1,
            int[] B,int s2,int e2){
        if(s1>e1||s2>e2)
            return null;
        int rootValue=A[s1];
        TreeNode root=new TreeNode(rootValue);
        if(s1==e1){
            if(s2==e2){
                if(A[s1]==B[s2])
                    return root;
                else {
                    return null;
                }
            }
        }
        int rootInorder=s2;
        while(rootInorder<=e2&&B[rootInorder]!=rootValue){
            rootInorder++;
        }
        int leftLength=rootInorder-s2;
        int rightLength=e2-rootInorder;
        int preOrderEnd=s1+leftLength;
        if(leftLength>0){//构建左子树
            root.left=constructTree(A, s1+1, preOrderEnd, B, s2, rootInorder-1);
        }
        if(rightLength>0){
            root.right=constructTree(A, preOrderEnd+1, e1, B, rootInorder+1, e2);
        }
        return root;


    }

    //7、用两个栈实现一个队列、两个队列实现一个栈
    //8、旋转数组的最小数字:递增排序的一个旋转数组,找出最小的元素 findMinRotatedArray
    //思路:左边指针最后指向最大的数,右边指针最后指向最小的数(无重复的情况)
    private static int findMinRotatedArray(int A[]){
        if(A==null||A.length<=0)
            return 0;
        int p1=0;
        int p2=A.length-1;
        int mid=0;
        while(A[p1]>=A[p2]){
            if(p2-p1==1){
                mid=p2;
                break;
            }
            mid=(p1+p2)/2;
            if(A[mid]>A[p1]){
                p1=mid;
            }else {
                p2=mid;
            }
        }
        return A[mid];
    }
    //14、调整数组顺序,使得奇数位于偶数前面 reorderOddEven
    private static void reorderOddEven(int A[]) {
        if(A==null||A.length<=1)
            return;
        int i=0;
        int j=A.length-1;
        while(i<j){
            while((A[i]&1)!=0){//找偶数
                i++;
            }
            while((A[j]&1)==0){
                j--;
            }
            if(i<j)
                swap(A,i,j);
        }

    }
    private static void swap(int[] A,int i,int j) {
        A[i]=A[i]^A[j];
        A[j]=A[i]^A[j];
        A[i]=A[i]^A[j];

    }
    //18、判断树B是否为树A的子结构
    private static boolean hasSubTree(TreeNode A,TreeNode B){
        boolean result=false;
        if(A!=null&&B!=null){
            if(A.val==B.val){
                result=isSubTree(A,B);
            }
            if(!result){
                hasSubTree(A.left, B);
            }
            if(!result){
                hasSubTree(A.right, B);
            }
        }
        return result;
    }

    private static boolean isSubTree(TreeNode a, TreeNode b) {
        if(a==null)
            return false;
        if(b==null)
            return true;
        if(a.val!=b.val)
            return false;
        return isSubTree(a.left, b.left)&&isSubTree(a.right, b.right);
    }
    //20、顺时针打印矩阵,从外向里顺序打印每一个数字printMatrix
    private static void printMatrix(int[][] mat,int columns,int rows){
        if(mat==null||columns<=0||rows<=0)
            return;
        int start=0;
        while(columns>start*2&&rows>start*2){
            printMatrixCircle(mat,columns,rows,start);
            ++start;
        }
    }

    private static void printMatrixCircle(int[][] mat, int columns, int rows,
            int start) {
        int xEnd=columns-start-1;
        int yEnd=rows-start-1;
        for(int i=start;i<=xEnd;i++){//从左到右打印up行
            System.out.print(mat[start][i]+" ");
        }
        for(int j=start+1;j<=yEnd;j++){//从上到下打印right行
            System.out.print(mat[j][xEnd]+" ");
        }
        if(start<yEnd){
            for(int i=xEnd-1;i>=start;i--){//从右到到左打印down行
                System.out.print(mat[yEnd][i]+" ");
            }
        }
        if(start<yEnd-1){
            for(int j=yEnd-1;j>start;j--){//从下到上打印left行
                System.out.print(mat[j][start]+" ");
            }
        }


    }
    //23、栈的压入弹出序列,序列A:压栈序列,序列B:出栈序列,判断B是否正确?isPopOrder
    private static boolean isPopOrder(int[] A,int[] B){
        if(A==null||B==null)
            return false;
        if(A.length!=B.length){
            return false;
        }
        Stack<Integer> stacks=new Stack<Integer>();
        int i=0;//A index
        int j=0;//B index
        int len=B.length;
        while(j<len){
            if(stacks.empty()||stacks.peek()!=B[j]){
                if(i>=len){
                    break;
                }
                stacks.push(A[i++]);
            }
            if(stacks.peek()!=B[j])
                break;
            stacks.pop();
            j++;

        }
        if(stacks.empty()&&j==len)
            return true;
        return false;
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值