【剑指offer】java实现

剑指offer
面试题4:二维数组中的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
代码:
public class Solution {
    public boolean Find(int target, int [][] array) {
        for(int i=0;i arrayList=new ArrayList<>();
    public ArrayList printListFromTailToHead(ListNode listNode) {
        if(listNode!=null){
       this.printListFromTailToHead(listNode.next);
           arrayList.add(listNode.val);
   }
       return arrayList;
    }
}
面试题7:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
代码:
/**
 * 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;
    }
    
    public TreeNode reConstructBinaryTree(int[] pre,int preStart,int preEnd,int[] in,int inStart,int inEnd){
        //表示数组为空
        if(preStart>preEnd || inStart>inEnd){
            return null;
        }
        TreeNode root=new TreeNode(pre[preStart]);
        for(int i=inStart;i<=inEnd;i++){
            if(in[i]==pre[preStart]){
                root.left=reConstructBinaryTree(pre,preStart+1,preStart+i-inStart,in,inStart,i-1);
                root.right=reConstructBinaryTree(pre,i-inStart+preStart+1,preEnd,in,i+1,inEnd);
            }
        }
        return root;
    }
}
面试题9:用两个栈实现队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
代码:
import java.util.Stack;

public class Solution {
    Stack stack1 = new Stack();
    Stack stack2 = new Stack();
    
    public void push(int node) {
        //进队列的方法和栈是一样的
        stack1.push(node);
    }
    
    public int pop() {
      //如果第出栈为空那么我们就将第一个栈里面的元素进栈
        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
        }
      return stack2.pop();
}
}
面试题11:旋转数组中最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
代码:
import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
            if(array.length==0){
            return 0;
        }else{
            for(int i=0;iarray[i+1]){
                    return array[i+1];
                }else {
                    if(i==array.length-2){
                        return array[0];
                    }
                }
            }
        }
        return 0;
    }
}
面试题10:斐波那契额数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
代码:
public class Solution {
    public int Fibonacci(int n) {
    if(n<0) {
            return 0;
        }else if(n==1||n==2){
            return 1;
        } 
        return Fibonacci(n-1)+Fibonacci(n-2);
    }
}
面试题8:跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
代码:
public class Solution {
    public int JumpFloor(int target) {
        if(target<0){
            return 0;
        }else if(target==1){
            return 1;
        }else if(target==2){
            return 2;
        }
        else {
            int one=1;
            int two=2;
            int result=0;
            for(int i=2;i0){
            for(int i=1;i<=exponent;i++){
                result=result*base;
                if(result>1.7976931348623157E308){
                    System.out.println("已经超出了double类型的范围");
                    return -1;
                }
            }
            return result;
        }
        if(exponent<0){
            exponent=-exponent;
            for(int i=1;i<=exponent;i++){
                result=result*base;
                if(result>1.7976931348623157E308){
                    System.out.println("已经超出了double类型的范围");
                    return -1;
            }
        }
        result=1.0/result;
            return result;
    }else {
            return 1;
        }
  }
}
面试题21:调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
代码:
public class Solution {
    public void reOrderArray(int [] array) {
                for(int i=0;i=list2.val){
            result=list2;
            result.next=Merge(list1,list2.next);
            
        }
        
        return result;
    }
}
面试题17:树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
代码:
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
         if(root2==null){
            return false;
        }
        if(root1==null&&root2!=null){
            return false;
        }
         boolean result=false;
        if(root1.val==root2.val){
            result=isSameTree(root1,root2);
        }
        
        if(!result){
            result=HasSubtree(root1.left,root2);
            if(!result){
                result=HasSubtree(root1.right,root2);
            }
        }
        
        return result;
        
    }
    
    //在进行判断一个树是否为另外一个树的子树的时候我们首先需要直到如何判断两棵树的结构是相同的树
    public boolean isSameTree(TreeNode root1,TreeNode root2){
        if(root2==null){
            return true;
        }
        if(root1==null&&root2!=null){
            return false;
        }
        //下面是两个树都不为空树的情况
        if(root1.val==root2.val){
            return isSameTree(root1.left,root2.left) && isSameTree(root1.right,root2.right);
        }
        return false;
    }
}
面试题27:二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树 
    	    8
    	   /  \
    	  6   10
    	 / \  / \
    	5  7 9 11
    	镜像二叉树
    	    8
    	   /  \
    	  10   6
    	 / \  / \
    	11 9 7  5
代码:
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    //将一棵树变为它镜像树就是判断其根节点是否为空,如果为空则不是。如果不为空则将其左右子树进行交换
    public void Mirror(TreeNode root) {
        if(root==null){
            return;
        }
        TreeNode temp;
        if(root!=null){
            temp=root.left;
            root.left=root.right;
            root.right=temp;
            
            if(root.left!=null){
                Mirror(root.left);
            }
            if(root.right!=null){
                Mirror(root.right);
            }
        }
    }
}
面试题29:顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
代码:
import java.util.ArrayList;
public class Solution {
    public ArrayList printMatrix(int [][] matrix) {
        //定义一个集合来存放按照题目顺序输出的集合元素
        ArrayList result=new ArrayList<>();
       if(matrix==null||matrix.length==0){
           return result;
       }
           printMatrixClockWisely(matrix, 0, 0, matrix.length - 1, matrix[0].length - 1, result);
           return result;
    }
    public void printMatrixClockWisely(int[][] matrix,int startRow,int startCol,int endRow,int endCol,ArrayList result){
            if(startRow=startCol; j--){
                    result.add(matrix[endRow][j]);
                }
                //从下向上
                for(int i=endRow-1; i>=startRow+1; i--){
                    result.add(matrix[i][startCol]);
                }
                printMatrixClockWisely(matrix,startRow+1,startCol+1,endRow-1,endCol-1,result);
            }else if(startRow==endRow && startCol stack1=new Stack<>();
    Stack min=new Stack<>();
    public void push(int node) {
        stack1.push(node);
        if(min.isEmpty()){
            min.push(node);
        }else{
            int top=min.peek();
            if(node stack = new Stack();
        int j=0;
        for(int i=0;i PrintFromTopToBottom(TreeNode root) {
        //首先定义一个集合,存放层序遍历二叉树以后的节点
        ArrayList list=new ArrayList<>();
        if(root==null){
            return list;
        }
        Queue queue=new LinkedList();
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode t=queue.poll();
            list.add(t.val);
             if(t.left!=null){
            queue.add(t.left);
        }
        if(t.right!=null){
            queue.add(t.right);
        }
      }
        return list;
    }
}
面试题33:二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
代码:
public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        //首先我们需要分析二叉搜索树的特点,然后再进行分析后需遍历二叉搜索树的特点:
        //就是后序遍历二叉搜索树,最后一个节点就是根节点,根节点的前面如果出现了比它大的节点
        //那么这个节点以后数组里的所有节点都应该比它大,如果不满足那么就不是二叉搜索树的后序遍历的结果。
        if(sequence.length==0){
            return false;
        }
        return isTreeBST(sequence,0,sequence.length-1);
    }
    
    public boolean isTreeBST(int[] sequence,int start,int end){
        if(end<=start){
            return true;
        }
        int i;
        for(i=start;isequence[end]){
                break;
            }
        }
        for(int j=i;j> resultsList = new ArrayList>();
    public ArrayList> FindPath(TreeNode root,int target) {
        if(root==null){
            return resultsList;
        }
        int curSum=0;
        int index=0;
        int[] path=new int[1000];
        this.isTargetPath(root,target,curSum,path,index);
        
        return this.resultsList;
    }
    
    /**
    递归函数求解:
    把根节点到叶节点路径上的值加起来
    */
    public void isTargetPath(TreeNode eleNode,int target,int curSum,int[] path,int index){
        if(eleNode==null){
            return;
        }
        curSum+=eleNode.val;
         path[index] = eleNode.val;
            index++;
        if(curSum==target&&eleNode.left==null&&eleNode.right==null){
            //这个集合是存放满足条件的一条路径
            ArrayList pathList=new ArrayList<>();
            for(int i=0;i Permutation(String str) {
        ArrayList result = new ArrayList() ;
        if(str==null || str.length()==0) { return result ; }
 
        char[] chars = str.toCharArray() ;
        TreeSet temp = new TreeSet<>() ;
        Permutation(chars, 0, temp);
        result.addAll(temp) ;
        return result ;
    }
 
    public void Permutation(char[] chars, int begin, TreeSet result) {
        if(chars==null || chars.length==0 || begin<0 || begin>chars.length-1) { 
            return ; 
        }
        if(begin == chars.length-1) {
            result.add(String.valueOf(chars)) ;
        }else {
            for(int i=begin ; i<=chars.length-1 ; i++) {
                swap(chars, begin, i) ;
                Permutation(chars, begin+1, result);
                swap(chars, begin, i) ;
            }
        }
    }
    public void swap(char[] x, int a, int b) {
        char t = x[a];
        x[a] = x[b];
        x[b] = t;
    }
}
面试题39:数组中出现次数超多一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
代码:
import java.util.Arrays;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        int len=array.length;
        if(len<1){
            return 0;
        }
        int count=0;
        //采用java数组里面的排序
        Arrays.sort(array);
        //根据数组的特性:可以知道数组中的数字出现了超过它长度的一半的数字一定排序后一定在数组中出现
        int num=array[len/2];
        for(int i=0;i GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList list=new ArrayList<>();
        if(input.length==0||k==0||k>input.length){
            return list;
        }
        Arrays.sort(input);
        for(int i=0;igreatestSum){
                greatestSum=curSum;
            }
        }
        return greatestSum;
    }
}
面试题43:数组中1出现的次数
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
代码:
public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
    int num=0;
        for(int i=1;i<=n;i++){
            num+=numOf1(i);
        }
        return num;
    }
    
    public int numOf1(int n){
        int num=0;
        while(n!=0){
            if(n%10==1){
                num++;
            }
            n=n/10;
        }
        return num;
    }
}
面试题45:把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
代码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        int n;
        String s="";
        ArrayList list=new ArrayList<>();
        n=numbers.length;
        for(int i=0;i(){//这个是函数式接口
         
            //方法重载为:比较两个字符串的大小
            @Override
             public int compare(Integer str1, Integer str2) {
                 //与字符串连接的参数也会变成字符串
                 String s1=str1+""+str2;
                 String s2=str2+""+str1;
                    return s1.compareTo(s2);
             }
        });
        //此时集合里面存放的是最小的字符串排列,遍历集合进行拼接,然后返回
         for(int j:list){
            s+=j;
        }
        return s;
    }
}
面试题49:丑数
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
代码1:(超时)
public class Solution {
    public int GetUglyNumber_Solution(int index) {
        //注意:这个index表示有多少个丑数,但是它并不是我们真正的丑数,所以我们需要根据给定的index找到
        //这个index对应的是哪个丑数
        if(index<=0){
            return 0;
        }
        int numbers=0;
        //找到丑数的个数
        int uglyFound=0;
        while(uglyFound list=new ArrayList();
        list.add(1);
        int i2=0;
        int i3=0;
        int i5=0;
        while(list.size() map=new HashMap ();
        for(int i=0;i>1;
        int left=InversePairsCore(array,copy,start,mid)%1000000007;
        int right=InversePairsCore(array,copy,mid+1,end)%1000000007;
        
        int i=mid;//p1
        int j=end;//p2
        int copyIndex=end;//p3
        int count=0;
        while(i>=start&&j>=mid+1){
            if(array[i]>array[j]){
                copy[copyIndex--]=array[i--];
                count=count+(j-mid);//逆序对的数目就是右边数组的长度
                if(count>=1000000007){
                    count=count%1000000007;
                }
            }else{
                copy[copyIndex--]=array[j--];
            }
        }
        //最后还需要将data数组拷贝到copy数组里面
        for(;i>=start;i--){
            copy[copyIndex--]=array[i];
        }
        for(;j>=mid+1;j--){
            copy[copyIndex--]=array[j];
        }
        for(int s=start;s<=end;s++){//最后需要将array数组进行更新操作
            array[s]=copy[s];
        }
        return (count+left+right)%1000000007;
    }
}
面试题52:两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
代码:
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1==null||pHead2==null){
            return null;
        }
        //先分别获取两个链表的长度
        int len1=getListLength(pHead1);
        int len2=getListLength(pHead2);
        int diffLen=len1-len2;
        ListNode pListHeadLong=pHead1;
        ListNode pListHeadShort=pHead2;
        if(len2>len1){
            pListHeadLong=pHead2;
            pListHeadShort=pHead1;
            diffLen=len2-len1;
        }
        for(int i=0;i map=new HashMap();
        for(int i=0;iright?(left+1):(right+1);
    }
}
面试题56:平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
代码:
import java.lang.*;
public class Solution {
    //首先在做题之前我们需要知道什么是平衡二叉树:平衡二叉树就是左右子树的深度差值小于等于1
    public boolean IsBalanced_Solution(TreeNode root) {
        if(root==null){
            return true;
        }
        if(root.left==null&&root.right==null){
            return true;
        }
        int leftDepth=depthTree(root.left);
        int rightDepth=depthTree(root.right);
        int diff=Math.abs(leftDepth-rightDepth);
        return diff<=1?true:false;
    }
    //所以我们需要一个求得二叉树深度的函数
    public int depthTree(TreeNode root){
        if(root==null){
            return 0;
        }
        if(root.left==null&&root.right==null){
            return 1;
        }
        int left=depthTree(root.left);
        int right=depthTree(root.right);
        return left>right?(left+1):(right+1);
    }
}
面试题56:数组中只出现一次的数字——难题
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
代码:
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
  public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if(array.length < 2) return ;
        int myxor = 0;
        int flag = 1;
        for(int i = 0 ; i < array.length; ++ i )
            myxor ^= array[i];
        while((myxor & flag) == 0) flag <<= 1;
       // num1[0] = myxor;
        //num2[0] = myxor;
        for(int i = 0; i < array.length; ++ i ){
            if((flag & array[i]) == 0) num2[0]^= array[i];
            else num1[0]^= array[i];
        }
    }
}
面试题57:和为S的连续正数序列
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
代码:
import java.util.ArrayList;
public class Solution {
    public ArrayList > FindContinuousSequence(int sum) {
        //这道题最总要的就是理解题意:怎么样实现有序的进行序列和的相加,我们采用双指针的方法
       ArrayList> res=new ArrayList>();
       ArrayList list=new ArrayList<>();
        //(1)首先是如果这个传入的参数小于3,那么绝对不会满足题意出现两个数字之和等于它
        if(sum<3){
            return res; 
        }
        int small=1;
        int big=2;
        int cursum=small+big;
        int mid=(1+sum)/2;
        list.add(small);
        list.add(big);
        while(small FindNumbersWithSum(int [] array,int sum) {
        //还是采用快慢指针的方法,我们进行两个数的相加
        ArrayList res=new ArrayList<>();
        if(array.length<1){
            return res;
        }
        int small=0;
        int big=array.length-1;
        while(big>small){
            int cursum=array[big]+array[small];
            if(cursum==sum){
                break;
            }else if(cursum>sum){
                big--;
            }else{
                small++;
            }
        }
        if(array[small] queue=new LinkedList<>();
        //首先把这个字符串转化为字符
        for(int i=0;i0){
            Character ch=queue.poll();
            queue.add(ch);
            --n;
        }
        //下面就是将这个队列里面的元素取出来转化为String
        StringBuilder sb=new StringBuilder();
        while(!queue.isEmpty()){
            char temp=queue.poll();
            sb.append(temp);
        }
        String res=sb.toString();
        return res;
    }
}
面试题60:翻转单词顺序序列
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
代码:
public class Solution {
   public String ReverseSentence(String str) {
       //特殊情况
       if(str==null){
           return null;
       }
       if(str.trim().equals("")){
           return str;
       }
        //首先进行整体的翻转,然后再进行单个字符串的反转
        str=reverse(str);
        //然后再度每个字符串进行翻转
        String[] temp=str.split(" ");//以空格为标准将字符串进行分割
        for(int i=0;i=0){
            s.append(str.charAt(i));
            i--;
        }
        return s.toString();
    }
}
面试题61:扑克牌顺子
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
代码:
import java.util.*;
/*
1.分析可以知道如果0的个数大于等于间隔数都是顺子,此外需要注意如果出现了对子那么就一定不是顺子
2.统计0的个数
3.统计间隔数
4.进行比较
*/
public class Solution {
    public boolean isContinuous(int [] numbers) {
        if(numbers==null||numbers.length==0){
            return false;
        }
        Arrays.sort(numbers);
        int numberOfZero=0;//数组在0的个数
        int numberOfGap=0;//数组中不连续的间隔
        //统计0的个数
        for(int i=0;i list=new ArrayList<>();
        //将这n个数装进链表里面
        for(int i=0;i1){//表示链表里面的数字剩余的大于1个数
            index=(index+m)%list.size();
            list.remove(index);
            index--;
        }
        return list.get(0);
    }
}
面试题64:求1+2+3+……+n
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
代码:
public class Solution {
    public int Sum_Solution(int n) {
        /*
        方法一:我们通过我们实际的数字对该题进行分析以后可以得到我们这个加法的一些特性
        就能知道我们可以采用数学函数来解决这个问题
        */
 //       int sum=(int)(Math.pow(n,2)+n);
 //       sum=sum>>1;
 //       return sum;
        
        /*
        方法2:这个题本来最初的想法就是使用循环和递归来实现,但是因为限制我们使用循环的关键字
        但是我们可以通过短路来实现我们的递归终止条件
        */
        int sum=n;
        boolean ans=(n>0)&&((sum+=Sum_Solution(n-1))>0);
        return sum;
    }
}
面试题65:不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
代码:
public class Solution {
    public int Add(int num1,int num2) {
        /*
        首先看十进制是如何做的: 5+7=12,三步走
       第一步:相加各位的值,不算进位,得到2。
       第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
       第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
       同样我们可以用三步走的方式计算二进制值相加:
       第一步,5->101,7->111 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
       第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
       第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
       继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
        */
        while(num2!=0){
            int temp=num1^num2;//异或操作
            num2=(num1&num2)<<1;
            num1=temp;
        }
        return num1;
    }
}
面试题:把字符串转换成整数
将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
代码:
public class Solution {
    public int StrToInt(String str) {
        //首先进行判断这个传入的字符串是否为空
        if(str.equals("")||str.length()==0){
            return 0;
        }
        //接下来先判断符号位
        int fuhao=0;//用来标记符号位到底是正还是负的
        char[] ch=str.toCharArray();
        if(ch[0]=='-'){
            fuhao=1;
        }
        int sum=0;//用来记录我们转化为整数的结果
        for(int i=fuhao;i57) return 0;
            //下面这条语句是相加的关键:每次进行一次乘10相当于是扩大的一个级别,从个位-->十位-->百位
            sum=sum*10+(ch[i]-48);
        }
        return fuhao==0?sum:sum*-1;
    }
}
面试题:数组中的重复数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
代码:
public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
    //注意:我们的返回值是任意的一个重复的值
        if(length==0 || length==1){
            return false;
        }
        //采用双指针两层遍历
        for(int i=0;i=0;j--){
            temp*=A[j+1];
            B[j]*=temp;
        }
     }         
        return B;
    }
}
面试题19:正则表达式匹配
请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。
代码:
public class Solution {
    public boolean match(char[] str, char[] pattern){
if (str == null || pattern == null) {
        return false;
    }
    int strIndex = 0;
    int patternIndex = 0;
    return matchCore(str, strIndex, pattern, patternIndex);
}
  
public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) {
    //str到尾,pattern到尾,匹配成功
    if (strIndex == str.length && patternIndex == pattern.length) {
        return true;
    }
    //str未到尾,pattern到尾,匹配失败
    if (strIndex != str.length && patternIndex == pattern.length) {
        return false;
    }
    //str到尾,pattern未到尾(不一定匹配失败,因为a*可以匹配0个字符)
    if (strIndex == str.length && patternIndex != pattern.length) {
        //只有pattern剩下的部分类似a*b*c*的形式,才匹配成功
        if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') {
            return matchCore(str, strIndex, pattern, patternIndex + 2);
        }
        return false;
    }
      
    //str未到尾,pattern未到尾
    if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') {
        if (pattern[patternIndex] == str[strIndex] || (pattern[patternIndex] == '.' && strIndex != str.length)) {
            return matchCore(str, strIndex, pattern, patternIndex + 2)//*匹配0个,跳过
                    || matchCore(str, strIndex + 1, pattern, patternIndex + 2)//*匹配1个,跳过
                    || matchCore(str, strIndex + 1, pattern, patternIndex);//*匹配1个,再匹配str中的下一个
        } else {
            //直接跳过*(*匹配到0个)
            return matchCore(str, strIndex, pattern, patternIndex + 2);
        }
    }
      
    if (pattern[patternIndex] == str[strIndex] || (pattern[patternIndex] == '.' && strIndex != str.length)) {
        return matchCore(str, strIndex + 1, pattern, patternIndex + 1);
    }
      
    return false;
    }
}
面试题20:表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
代码:
public class Solution {
    //所有可能出现的情况
   // A[.[B]][e|EC]或者.B[e|EC],注意B是一个无符号整数
    private int index=0;
    public boolean isNumeric(char[] str) {
        if(str.length<1) return false;
       boolean flag = scanInteger(str);
        //如果出现'.',则接下来是数字的小数部分
        if (index < str.length && str[index] == '.') {
            index++;
             //下面一行代码用||的原因:
            //1.小数可以没有整数部分,如.123==0.123
            //2.小数点后面可以没有数字,如223.==223.0
            //3.当然,小数点前面和后面都可以有数字
            flag = scanUnsignedInteger(str) || flag;
        }
        //如果出现'e'或者'E',则接下来是数字的指数部分
         if (index < str.length && (str[index] == 'E' || str[index] == 'e')) {
            index++;
              //下面一行代码用&&的原因:
            //1.当e或者E前面没有数字的时候表示整个字符串不是数值类型
            //2.当e或者E后面没有数字的时候,整个字符串不是数值类型
            flag = flag && scanInteger(str);
        }
        return flag && index == str.length;
    }
    //函数scanInteger扫描可以表示正负的'+'或者'-'位起始位置的0——9的数位,类似于一个可能带正负符号的整数,
    //用来匹配前面的A和C部分
    private boolean scanInteger(char[] str){
       if (index < str.length && (str[index] == '+' || str[index] == '-') )
            index++;
        return scanUnsignedInteger(str);
    }
    //函数scanUnsignedInteger用来扫描字符串中0——9的数位(类似于一个无符号整数),可以用来匹配前面数值模式中的B部分
    private boolean scanUnsignedInteger(char[] str){
       int start = index;
        while (index < str.length && str[index] >= '0' && str[index] <= '9')
            index++;
        return start < index; //是否存在整数
    }
}
面试题:字符流中第一个不重复的字符
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
代码:
import java.util.HashMap;
import java.util.ArrayList;
public class Solution {
    //定义一个HashMap来存放字出现的字符串以及该字符串出现的次数
    HashMap map=new HashMap<>();
    //定义一个ArrayList用来存放这个字符流里面存在的字符,然后方便我们取出进行判断
    ArrayList list=new ArrayList();
    //Insert one char from stringstream
    public void Insert(char ch)
    {
        if(!map.containsKey(ch)){
            map.put(ch,1);
            list.add(ch);
        }else{
            map.put(ch,map.get(ch)+1);
        }
    }
  //return the first appearence once char in current stringstream
    public char FirstAppearingOnce()
    {
        for(int i=0;i > Print(TreeNode pRoot) {
        //采用两个栈来实现:一个栈用来存放奇数行结点(先存放右子树再存放左子树,因为对于栈来说它出栈的顺序正好是和进栈的顺序相同的)
        //一个用来存放偶数行结点(先存放左子树再存放右子树)
        int layer=1;//表示现在在第几层
        Stack s1=new Stack<>();
        s1.push(pRoot);
        Stack s2=new Stack<>();
        ArrayList> ret=new ArrayList>();
        while(!s1.isEmpty()||!s2.isEmpty()){
            if(layer%2==1){//表示奇数层
                ArrayList list=new ArrayList<>();
                while(!s1.isEmpty()){
                    TreeNode node=s1.pop();
                    if(node!=null){
                        list.add(node.val);
                        s2.push(node.left);//当前层是奇数层那么它的下一层就是偶数层
                        s2.push(node.right);
                    }
                }
                if(!list.isEmpty()){
                    ret.add(list);
                    layer++;
                }
            }else{//否则是偶数层
                ArrayList list=new ArrayList<>();
                while(!s2.isEmpty()){
                    TreeNode node=s2.pop();
                    if(node!=null){
                        list.add(node.val);
                        s1.push(node.right);
                        s1.push(node.left);
                    }
                }
                         if(!list.isEmpty()){
                        ret.add(list);
                        layer++;
                    }
            }
        }
        return ret;
    }
}
面试题:把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
代码:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    /**
    在二叉树的层序遍历上面多了一个判定当前层已经打印和总共结点个数之间的关系,因为它需要将每一层的结点存放到一个list里面
    而层序遍历其实是将所有的结点按照顺序存放到一个list里面的,所以这个地方就是区别点。
    **/
    ArrayList > Print(TreeNode pRoot) {
    //采用递归的方法将从根节点开始往下按照从左向右的顺序进行递归调用
        ArrayList> ret=new ArrayList>();
        if(pRoot==null){
            return ret;
        }
        Queue queue=new LinkedList<>();
        queue.add(pRoot);
        int count;//记录当前层已经打印的个数
        int last;//记录当前层一共有多少个
        while(!queue.isEmpty()){
            count=0;
            last=queue.size();
            ArrayList list=new ArrayList<>();
            //打印一层
            while(count queue=new LinkedList<>();
        //循环二叉树元素字符加入队列中
        for(int i=0;i queue){
        //从队列取出头元素并删除
        String value=queue.poll();
        //如果没有数据则退出递归
        if(value.equals("$"))  return null;
        TreeNode head=new TreeNode(Integer.valueOf(value));
        //递归得到当前孩子的左节点(遇到“$”结束)
        head.left=reconPreOrder(queue);
        //递归得到当前孩子的右节点(遇到“$”结束)
        head.right=reconPreOrder(queue);
        return head;
    }
}
面试题:二叉搜索树的第k个结点
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4。
代码:
import java.util.HashMap;
import java.util.Stack;
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
//    int count=0;//计数器
    //第一种:递归算法
//    TreeNode KthNode(TreeNode pRoot, int k)
//    {
//        if(pRoot==null){
//            return null;
//        }
//        //左子树
//        TreeNode node=KthNode(pRoot.left,k);
//        if(node!=null) return node;
//        //根节点
//        if(++count==k) return pRoot;
//        //右子树
//        node=KthNode(pRoot.right,k);
//        if(node!=null) return node;
//        return null;
//    }
    
    //第二种:非递归算法
     TreeNode KthNode(TreeNode pRoot, int k){
         if(pRoot==null||k==0) return null;
         int count=0;
         Stack stack=new Stack<>();
         while(pRoot!=null||!stack.isEmpty()){
             //按照中序遍历进行访问二叉树
             while(pRoot!=null){
                 stack.push(pRoot);//这个地方只是先把结点放进栈里面
                 pRoot=pRoot.left;//左子树
             }
             pRoot=stack.pop();//根节点
             count++;
             if(count==k) return pRoot;//右子树
             pRoot=pRoot.right;
         }
         return null;
     }
}
面试题:滑动窗口的最大值
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
代码:
import java.util.ArrayList;
public class Solution {
    public ArrayList maxInWindows(int [] num, int size)
    {
        ArrayList list=new ArrayList<>();
        if(size>num.length||size==0){
            return list;
        }
        int index=0;
        while((index+size)<=num.length){
        int[] arr=new int[size];
        for(int i=index,j=0;imax){
                max=array[i];
            }
        }
        return max;
    }
}


你可能感兴趣的:(DS)