《剑指Offer》Java版本 LeetCode

目录

    • 2 单例模式
    • 3 数组中重复的数字(Hash)
    • 4 二维数组中的查找
    • 5 替换空格
    • 6 从尾到头打印链表(栈)
    • 7 重建二叉树(递归)
    • 8 二叉树的下一个节点
    • 9 用两个栈实现队列(栈)
    • 10 I 斐波那契数列(循环)
    • 10 II青蛙跳台阶问题(循环)
    • 11 旋转数组的最小数字(二分)
    • 12 矩阵中的路径(回溯)
    • 13 机器人的运动范围(回溯)
    • 14 I 剪绳子 (动归)
    • 14 II 剪绳子(贪婪)
    • 15 二进制中1的个数(位运算)
    • 16 数值的整数次方(快速幂)
    • 17 打印从1到最大的n位数
    • 18 删除链表的节点(链表)
    • 19 正则表达式匹配(递归)
    • 20 表示数值的字符串(考察情况考虑是否完整)
    • 21 调整数组顺序使奇数位于偶数前面(双指针 模拟快排)
    • 22 链表中倒数第k个节点(双指针)
    • 23 链表中环的入口节点(双指针)
    • 24 反转链表(考察情况考虑是否完整)
    • 25 合并两个排序的链表(类似归并)
    • 26 树的子结构 (递归)
    • 27 二叉树的镜像(递归)
    • 28 对称的二叉树(递归)
    • 29 顺时针打印矩阵
    • 30 包含min函数的栈(辅助栈)
    • 31 栈的压入、弹出序列(辅助栈)
    • 32 I 从上到下打印二叉树(队列)
    • 32 II 从上到下打印二叉树(队列)
    • 32 III 之字形打印二叉树(两个栈)
    • 33 二叉搜索树的后序遍历序列(递归)
    • 34 二叉树中和为某一值的路径(回溯)
    • 35 复杂链表的复制
    • 36 二叉搜索树与双向链表
    • 37 序列化二叉树(递归)
    • 38 字符串的排列(回溯)
    • 39 数组中出现次数超过一半的数字
    • 40 最小的k个数 (快排/堆)
    • 41 数据流中的中位数(堆)
    • 42 连续子数组的最大和
    • 43 1~n整数中1出现的次数
    • 44 数字序列中某一位的数字
    • 45 把数组排成最小的数(排序规则)
    • 46 把数字翻译成字符串(动归)
    • 47 礼物的最大价值(动归)
    • 48 最长不含重复字符的子字符串(动归)
    • 49 丑数
    • 50 第一个只出现一次的字符(Hash)
    • 51 数组中的逆序对(归并)
    • 52 两个链表的第一个公共节点
    • 53 I 在排序数组中查找数字(二分)
    • 53 II 0~n-1中缺失的数字(二分)
    • 53III 数组中数值和下标相等的元素(二分)
    • 54 二叉搜索树的第k大节点(栈)
    • 55 I 二叉树的深度
    • 55 II 平衡二叉树
    • 56 数组中数字出现的次数(异或)
    • 56 II 数组中数字出现的次数 (位运算)
    • 57 和为s的两个数字(双指针)
    • 57 II 和为s的连续正数序列(双指针)
    • 58 I 翻转单词顺序
    • 58 II 左旋转字符串
    • 59 I 滑动窗口的最大值(双端队列)
    • 59 II 队列的最大值(双端队列)
    • 60 n个骰子的点数
    • 61 扑克牌中的顺子
    • 62 圆圈中最后剩下的数字
    • 63 股票的最大利润
    • 64 求1+2+…+n(逻辑运算)
    • 65 不用加减乘除做加法(逻辑运算)
    • 66 构建乘积数组
    • 67 把字符串转换成整数(注意考虑情况完整)
    • 68 I 二叉搜索树的最近公共祖先(递归)
    • 68 II 二叉树的最近公共祖先(递归)

2 单例模式

双重检验懒汉式单例模式

// 懒汉式(线程安全,同步方法) 
class Singleton {
	//volatile禁止重排序,保证可见性
	private static volatile Singleton instance;
	private Singleton() {}//私有化构造方法
	//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
	//同时保证了效率, 推荐使用
	public static synchronized Singleton getInstance() {
		if(instance == null) {
			synchronized (Singleton.class) { 
				if(instance == null) {
					instance = new Singleton();
				}
			}
		}
		return instance;
	}
}

3 数组中重复的数字(Hash)

LeetCode地址
题目描述:
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
思路:
(1)HashSet找重复数字
(2)数组交换,利用 0~n-1这个条件,类似位图的思想。边排序边判断。
代码:

class Solution {
    public int findRepeatNumber(int[] nums) {
        for(int i=0;i<nums.length;i++){
            while(nums[i]!=i){
            //不等的话,进行交换
                if(nums[i]==nums[nums[i]]){
                //如果已经存在数字了,说明重复
                    return nums[i];
                }
                int tmp=nums[i];
                nums[i]=nums[tmp];
                nums[tmp]=tmp;
            }
        }
        return -1;
    }
}

考虑另外一种情况,如果不允许交换数组中元素,如何解决?
方法一:

import java.util.*;
class Solution {
    public int findRepeatNumber(int[] nums) {
        HashSet<Integer> set=new HashSet<>();
        for(int i=0;i<nums.length;i++){
            if(set.contains(nums[i]))
                return nums[i];
            else set.add(nums[i]);
        }
        return -1;
    }
}

4 二维数组中的查找

LeetCode地址

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

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

5 替换空格

LeetCode地址
题目描述:
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
思路:注意不要覆盖(Java的String不需要考虑这个)

class Solution {
    public String replaceSpace(String s) {
        char arr[]=s.toCharArray();
        StringBuilder ret=new StringBuilder("");
        for(int i=0;i<arr.length;i++){
            if(arr[i]==' '){
                ret.append("%20");
            }else{
                ret.append(arr[i]);
            }
        }
        return ret.toString();
    }
}

6 从尾到头打印链表(栈)

LeetCode地址
题目描述:
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
思路:
(1)翻转链表之后再遍历
(2)利用栈,推荐
(3)递归的方式,链表很长可能会栈溢出,不推荐
栈的方式:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
import java.util.Stack;
class Solution {
    public int[] reversePrint(ListNode head) {
        Stack<ListNode> stack=new Stack<>();
        while(head!=null){
            stack.add(head);
            head=head.next;
        }
        int ret[]=new int[stack.size()];
        int len=0;
        while(!stack.isEmpty()){
            ret[len++]=stack.pop().val;
        }
        return ret;
    }
}

7 重建二叉树(递归)

LeetCode地址
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
代码:

/**
 * Definition for a binary tree node
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length<1||inorder.length<1) return null;
        TreeNode node=new TreeNode(preorder[0]);
        TreeNode leftN=null;
        TreeNode rightN=null;
        for(int i=0;i<inorder.length;i++){
            if(inorder[i]==node.val){
                leftN=buildTree(Arrays.copyOfRange(preorder,1,i+1),Arrays.copyOfRange(inorder,0,i));
                rightN=buildTree(Arrays.copyOfRange(preorder,i+1,preorder.length),Arrays.copyOfRange(inorder,i+1,inorder.length));
                break;
            }
        }
        node.left=leftN;
        node.right=rightN;
        return node;
    }
}

8 二叉树的下一个节点

牛客网地址
题目描述:
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
思路:判断是否有右子树

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;
    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode==null) return null;
        if(pNode.right!=null){//结点有右子树
            //找右子树最左边的结点
            pNode=pNode.right;
            while(pNode.left!=null){
                pNode=pNode.left;
            }
            return pNode;
        }else{//结点没有右子树
            //向上找到结点是父结点的左结点的结点
            while(pNode.next!=null&&pNode==pNode.next.right){
                    pNode=pNode.next;
            } 
            return pNode.next;
        }
    }
}

9 用两个栈实现队列(栈)

LeetCode地址
题目描述:
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
思路:
方法一,stack1始终存放压入队列的正序,stack2来倒换数据
方法二,对方法一改进,判断stack2如果为空再把stack1导入进来,stack2不为空直接返回栈顶元素
方法一:

import java.util.Stack;
class CQueue {
    Stack<Integer> stack1;
    Stack<Integer> stack2;
    public CQueue() {
        stack1=new Stack<>();
        stack2=new Stack<>();
    }
    
    public void appendTail(int value) {
        stack1.add(value);
    }
    
    public int deleteHead() {
    	//stack1放到stack2中
        while(!stack1.isEmpty()){
            stack2.add(stack1.pop());
        }
        if(stack2.isEmpty()){
            return -1;
        }else{//stack2的数据倒回stack1
            int ret=stack2.pop();
            while(!stack2.isEmpty()){
                stack1.add(stack2.pop());
            }
            return ret;
        }
    }
}

方法二:

import java.util.Stack;
class CQueue {
    Stack<Integer> stack1;
    Stack<Integer> stack2;
    public CQueue() {
        stack1=new Stack<>();
        stack2=new Stack<>();
    }
    
    public void appendTail(int value) {
        stack1.add(value);
    }
    
    public int deleteHead() {
        if(stack2.isEmpty()){
            if(stack1.isEmpty()){
                return -1;
            }else{
                while(!stack1.isEmpty()){
                    stack2.add(stack1.pop());
                }
                return stack2.pop();
            }   
        }else{
            return stack2.pop();
        }
    }
}

相关题目:
225.用队列实现栈
232.用栈实现队列

10 I 斐波那契数列(循环)

LeetCode地址
题目描述:
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

class Solution {
    public int fib(int n) {
        if(n<=1) return n;
        int opt1=0;
        int opt2=1;
        int ret=0;
        for(int i=0;i<n-1;i++){
            ret=(opt1+opt2)%1000000007;
            opt1=opt2;
            opt2=ret;
        }
        return ret;
    }
}

10 II青蛙跳台阶问题(循环)

LeetCode地址
题目描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

class Solution {
    public int numWays(int n) {
        if(n<=1) return 1;
        int opt1=1;
        int opt2=1;
        int ret=0;
        for(int i=0;i<n-1;i++){
            ret=(opt1+opt2)%1000000007;
            opt1=opt2;
            opt2=ret;
        }
        return ret;
    }
}

11 旋转数组的最小数字(二分)

LeetCode地址
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
方法一:复杂度为O(n)

class Solution {
    public int minArray(int[] numbers) {
        for(int i=1;i<numbers.length;i++){
            if(numbers[i-1]>numbers[i])
                return numbers[i];
        }
        return numbers[0];
    }
}

方法二:复杂度为O(logn) 二分法

class Solution {
    public int minArray(int[] numbers) {
        int left=0;
        int right=numbers.length-1;
        int mid;
        while(left<right&&(right-left!=1)){
            mid=(left+right)>>1;
            //无法判断有序
            if(numbers[mid]==numbers[right]){
                right--;
                continue;
            }//无法判断有序
            if(numbers[mid]==numbers[left]){
                left++;
                continue;
            }
            if(numbers[mid]<numbers[right]){
                right=mid;
            }else if(numbers[left]<numbers[mid]){
                left=mid;
            }
            
        }
        return Math.min(numbers[left],numbers[right]);
    }
}

12 矩阵中的路径(回溯)

LeetCode地址
题目描述:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。

class Solution {
    public boolean exist(char[][] board, String word) {
        for(int i=0;i<board.length;i++){
            for(int j=0;j<board[0].length;j++){
                if(backTrace(board,word,0,i,j)){
                        return true;
                }
            }
        }
        return false;
    }
    public boolean backTrace(char[][] board,String target,int len,int row,int col){
        if(row<0||row>=board.length||col<0||col>=board[0].length||
            board[row][col]!=target.charAt(len)) return false;
        if(len==target.length()-1){
                return true;
        }else{
            char tmp=board[row][col];
            board[row][col]='*';
            len++;
            if(backTrace(board,target,len,row-1,col)||
            backTrace(board,target,len,row+1,col)||
            backTrace(board,target,len,row,col-1)||
            backTrace(board,target,len,row,col+1)){
                return true;
            }else{
                board[row][col]=tmp;
                return false;
            }
        }
    }
}

13 机器人的运动范围(回溯)

LeetCode地址
题目描述:
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

class Solution {
    int count=0;
    public int movingCount(int m, int n, int k) {
        boolean []flag=new boolean[m*n];
        for(int i=0;i<flag.length;i++){//初始化
            flag[i]=false;
        }
        backTrace(0,0,m,n,flag,k);
        return count;
    }
    public void backTrace(int row,int col,int m,int n,boolean[] flag,int k){
        if(row<0||col<0||row>=m||col>=n) return;
        if(!flag[row*n+col]&&isValid(row,col,k)){
        	count++;
            flag[row*n+col]=true;//使其不会重复计数
            backTrace(row-1,col,m,n,flag,k);
            backTrace(row+1,col,m,n,flag,k);
            backTrace(row,col-1,m,n,flag,k);
            backTrace(row,col+1,m,n,flag,k);
        }
    }//判断位数之和是否大于k
    public boolean isValid(int row,int col,int k){
        int tmp1=0;
        int tmp2=0;
        while(row!=0){
            tmp1+=row%10;
            row=row/10;
        }
        while(col!=0){
            tmp2+=col%10;
            col=col/10;
        }
        if(tmp1+tmp2<=k){
            return true;
        }else{
            return false;
        }
    }
}

14 I 剪绳子 (动归)

LeetCode地址
题目描述:
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m] 。请问 k[0]k[1]…*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
方法一:动归

class Solution {
    public int cuttingRope(int n) {
        int dp[]=new int[n+1];
        if(n<=2) return 1;
        if(n==3) return 2;
        //dp[i]表示长度为i的最大乘积
        dp[0]=0;
        dp[1]=1;
        dp[2]=2;
        dp[3]=3;
        for(int i=4;i<n+1;i++){
            int tmp=Integer.MIN_VALUE;
            for(int j=1;j<=i/2;j++){
                if(dp[j]*dp[i-j]>tmp){
                    tmp=dp[j]*dp[i-j];
                }
            }
            dp[i]=tmp;
        }
        return dp[n];

    }
}

方法二:贪婪

public int cuttingRope(int n) {
        int dp[]=new int[n+1];
        if(n<=2) return 1;
        if(n==3) return 2;
        int num3=n/3;
        if(n-num3*3==1){//剩下为1的时候,最好4=2*2
            num3--;
        }
        int num2=(n-num3*3)/2;
        int ret=(int)Math.pow(3,num3)*(int)Math.pow(2,num2);
        return ret;
    }

14 II 剪绳子(贪婪)

LeetCode地址
题目描述:大整数求余问题
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
方法一:循环求幂

class Solution {
    public int cuttingRope(int n) {
        int dp[]=new int[n+1];
        if(n<=2) return 1;
        if(n==3) return 2;
        int num3=n/3;
        if(n-num3*3==1){
            num3--;
        }
        int num2=(n-num3*3)/2;
        //!!注意这里
        long tmp=cpow(3,num3,(int)Math.pow(2, num2));
        int ret=(int)tmp%1000000007;
        return ret;
    }
    //求幂函数
    public long cpow(int pow,int n,int start){
        long ret=start;
        while(n>0){
            ret=(ret*pow)%1000000007;
            n--;
        }
        return ret;
    }
}

方法二:快速幂
11的二进制为1011,
在这里插入图片描述
那么 a^11为:
在这里插入图片描述

修改求幂函数为:

//快速幂
    public long cpow1(long pow,int n,int start){
    	
        long ret=start;
        while(n>0){
            if((n&1)==1){//取最后一位是0还是1
                ret=(ret*pow)%1000000007;
            }
            n=n>>1;
            pow=pow*pow%1000000007;//底数为原来的平方,a 的2次方,a的4次方 ,a的8次方
        }
        return ret;
    }

15 二进制中1的个数(位运算)

LeetCode地址
题目描述:
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
思路:
普通解法,如果输入是负数会出现死循环的问题(因为负数右移时会补1,正数右移时补0)。

方法一:用右移mask代替左移n。每次需要循环32次。

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int ret=0;
        int tmp=1;
        while(tmp!=0){
            if((n&tmp)==tmp){
                ret++;
            }
            tmp=tmp<<1;
        }
        return ret;
    }
}

方法二:考虑(n-1)&n,
n-1表示把最后一位的1变为0,0之后的数为1
(n-1)&n表示把n的最后一位的1变为0。
例子:n=1011的情况,
《剑指Offer》Java版本 LeetCode_第1张图片

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int ret=0;
        while(n!=0){
            n=n&(n-1);
            ret++;
        }
        return ret;
    }
}

相关题目:
(1)判断整数是否是2的整数次方: (n-1)&n==0
(2)改变m二进制多少位得到n:异或后求1的位数

16 数值的整数次方(快速幂)

LeetCode地址
题目描述:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
注意:int32的取值范围是[-2147483648,2147483647],输入为2.0,-2147483648的情况会越界,解决办法用long操作inf

class Solution {
    public double myPow(double x, int n) {
        //快速幂
        if(x==0.0) return 0.0;
        if(n==1) return x;
        double ret=1;
        long tmp=n;//注意这里!!用long类型存储n
        long n1=Math.abs(tmp);
        while(n1!=0){
            if((n1&1)==1)
                ret=ret*x;
            n1=n1>>1;
            x=x*x;
        }
        if(n>=0) return ret;
        else{
            return 1.0/ret;
        }
    }
}

17 打印从1到最大的n位数

LeetCode地址
题目描述:
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。

class Solution {
    public int[] printNumbers(int n) {
        int len=1;
        while(n>0){
            len=len*10;
            n--;
        }
        len--;
        int []ret=new int[len];
        len=1;
        for(int i=0;i<ret.length;i++){
            ret[i]=len;
            len++;
        }
        return ret;
    }
}

相关题目:考虑大数的情况,解决办法:用字符串存大数

18 删除链表的节点(链表)

LeetCode地址
题目描述:
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
方法一:存储前一个节点,pre–>thisNode.next


class Solution {
    public ListNode deleteNode(ListNode head, int val) {
        ListNode top=new ListNode(0);
        top.next=head;
        ListNode node=head;
        ListNode tmp=top;
        while(node!=null){
            if(node.val==val){
                tmp.next=node.next;
                break;
            }
            tmp=node;
            node=node.next;
        }
        return top.next;
    }
}

方法二:复制this节点next节点的val给this节点,this节点的next指向next节点的next
《剑指Offer》Java版本 LeetCode_第2张图片

19 正则表达式匹配(递归)

LeetCode 地址 面试题19. 正则表达式匹配
题目描述:
请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。

class Solution {
    public boolean isMatch(String s, String p) {
        if(s==null||p==null) return false;
        return matchCore(s,p,0,0);
    }
    public boolean matchCore(String s,String p,int points,int pointp){
        if(s.length()==points&&p.length()==pointp) return true;
        if(s.length()>points&&p.length()==pointp) return false;
        //下一个为*的情况
        if(pointp+1<p.length()&&p.charAt(pointp+1)=='*'){
            //判断当前是否是. 或者相等
            if((points<s.length()&&p.charAt(pointp)=='.')||
            (points<s.length()&&s.charAt(points)==p.charAt(pointp))){
                return matchCore(s,p,points,pointp+2)||   //忽略b*
                        matchCore(s,p,points+1,pointp+2)||  //选择一个
                        matchCore(s,p,points+1,pointp);    //选择多个
            }else{//忽略b*
                return matchCore(s,p,points,pointp+2);
            }
        }
        //正常继续递归 s和p相等或者p是.
        if(points<s.length()&&(s.charAt(points)==p.charAt(pointp)||p.charAt(pointp)=='.')){
            return matchCore(s,p,points+1,pointp+1);
        }
        return false;
    }
}

20 表示数值的字符串(考察情况考虑是否完整)

LeetCode 地址

class Solution {
public boolean isNumber(String s) {
        //A.B e/E A
        if(s==null) return false;
        s=s.trim();
        boolean ret=isA(s)||isB(s);
        if(ret) return true;
        ret=isDouble(s);
        if(ret) return true;

        int index=s.indexOf("e");
        if(index+1<s.length()&&index!=-1){//判断是否是e
            //e前面是A A.B .B B
        	ret=isDouble(s.substring(0,index))||isA(s.substring(0,index))||isB(s.substring(0,index));
            //e后面是B
            ret= ret&&(isB(s.substring(index+1,s.length()))||isA(s.substring(index+1,s.length())));
        }
        if(ret) return true;
        index=s.indexOf("E");
        if(index+1<s.length()&&index!=-1){//判断是否是e
            //e前面是A A.B .B B
        	ret=isDouble(s.substring(0,index))||isA(s.substring(0,index))||isB(s.substring(0,index));
            //e后面是B
            ret= ret&&(isB(s.substring(index+1,s.length()))||isA(s.substring(index+1,s.length())));
        }
        if(ret) return true;
        return false;

    }
    //判断是否是 A.B|.B |B. | A.
    public boolean isDouble(String s) {
    	if(s.length()>0&&(s.charAt(0)=='+'||s.charAt(0)=='-')){
            s=s.substring(1,s.length());
        }
    	int index=s.indexOf(".");
    	boolean ret=false;
        if(index!=-1){//是否是A.B  .B B.
        	boolean dotPre=isA(s.substring(0,index))||isB(s.substring(0,index));
        	boolean dotAfter=false;
        	if(index+1<s.length()){
        		dotAfter=isB(s.substring(index+1,s.length()));
        		ret=(dotPre&&dotAfter)||(index==0&&dotAfter);
        	}else{
        		ret=index==s.length()-1&&dotPre;
        	}
            
        }
        return ret;
	}
    //判断是否是有符号整数
    public boolean isA(String s){
        if(s.length()>0&&(s.charAt(0)=='+'||s.charAt(0)=='-')){
            if(isB(s.substring(1,s.length())))
                return true;
        }
        return false;
    }
    //判断是否是无符号整数
    public boolean isB(String s){
        if(s.length()<1){
            return false;
        }
        for(int i=0;i<s.length();i++){
            if(!Character.isDigit(s.charAt(i))){
                return false;
            }
        }        
        return true;
    }
}

21 调整数组顺序使奇数位于偶数前面(双指针 模拟快排)

LeetCode地址

class Solution {
    public int[] exchange(int[] nums) {
        if(nums==null) return null;
        int low=0;
        int high=nums.length-1;
        while(low<high){
            while(low<high&&(nums[low]&1)==1)
                low++;
            while(low<high&&(nums[high]&1)==0)
                high--;
            int tmp=nums[low];
            nums[low]=nums[high];
            nums[high]=tmp;
        }
        return nums;
    }
}

22 链表中倒数第k个节点(双指针)

面试题22. 链表中倒数第k个节点
注意代码的鲁棒性!
考虑输入为k=0,k>链表长度,head==null的情况

class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        if(head==null||k<=0) return null;//here!!!!
        ListNode low=head;
        ListNode high=head;
        while(high!=null&&k-1>0){
            high=high.next;
            k--;
        }
        while(high!=null&&high.next!=null){//here
            high=high.next;
            low=low.next;
        }
        return low;
    }
}

23 链表中环的入口节点(双指针)

142. 环形链表 II LeetCode
题目描述:
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
方法一:Hashset

Set<ListNode> set=new HashSet<>();
		 ListNode temp=new ListNode(0);
		 int count=0;
		 while(head!=null){
			 count++;
			 set.add(head);
			 if (set.size()!=count) {
				temp=head;
				break;
			}
			 head=head.next;
		 }
		 if (head==null) {
			return null;
		}
		return temp;

方法二:双指针


public class Solution {
    //判断是否有环,有环返回环中的位置
    public ListNode hasCycle(ListNode head) {
        ListNode node=head;//慢指针
        while(head!=null&&head.next!=null){
            head=head.next.next;
            node=node.next;
            if(head==node) return head;
        }
        return null;
    }
    public ListNode detectCycle(ListNode head) {
        ListNode node=hasCycle(head);
        if(node==null) return null;
        //找出环中节点数量
        int len=1;
        ListNode tmp=node;
        while(node.next!=tmp){
            node=node.next;
            len++;
        }
        //双指针找到节点
        node=head;
        tmp=head;
        while(len>0){
            node=node.next;
            len--;
        }
        while(node!=tmp){
            node=node.next;
            tmp=tmp.next;
        }
        return node;
    }
}

24 反转链表(考察情况考虑是否完整)

面试题24. 反转链表 LeetCode
题目描述:
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null) return null;//输入空节点
        if(head.next==null) return head; //输入只有一个节点
        ListNode pre=head;
        ListNode thisNode=head.next;
        ListNode nextNode=thisNode.next;
        pre.next=null;//注意这里 如果不设置会有环产生
        while(thisNode!=null){
            nextNode=thisNode.next;
            thisNode.next=pre;
            pre=thisNode;
            thisNode=nextNode;
        }
        return pre;
    }
}

25 合并两个排序的链表(类似归并)

面试题25. 合并两个排序的链表 LeetCode地址
题目描述:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head=new ListNode(-1);
        ListNode node=head;
        while(l1!=null&&l2!=null){
            if(l1.val<l2.val){
                node.next=l1;
                l1=l1.next;
            }else{
                node.next=l2;
                l2=l2.next;
            }
            node=node.next;
        }
        if(l1!=null){
            node.next=l1;
        }
        if(l2!=null){
            node.next=l2;
        }
        return head.next;
    }
}

相关题目: 23.合并K个排序链表

26 树的子结构 (递归)

面试题26. 树的子结构
题目描述:输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构),B是A的子结构, 即 A中有出现和B相同的结构和节点值。

class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(A==null||B==null) return false;//注意边界
        //A.val==B.val就判断是否是子树,不等就在左子树和右子树中寻找
        return isSubTree(A,B)|| isSubStructure(A.left,B)||isSubStructure(A.right,B);
    }
    public boolean isSubTree(TreeNode A,TreeNode B){
        if(B!=null&&A==null) return false;
        if(B==null) return true;
        if(A.val==B.val){
            return isSubTree(A.left,B.left)&&isSubTree(A.right,B.right);
        }else{
            return false;
        } 
    }
}

27 二叉树的镜像(递归)

面试题27. 二叉树的镜像 LeetCode地址
题目描述:请完成一个函数,输入一个二叉树,该函数输出它的镜像。

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root==null) return null;
        TreeNode left=mirrorTree(root.left);
        TreeNode right=mirrorTree(root.right);
        root.left=right;
        root.right=left;
        return root;
    }
}

28 对称的二叉树(递归)

LeetCode地址

题目描述:
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null) return true;
        else return core(root.left, root.right);
    }
    public boolean core(TreeNode left,TreeNode right){

        if(left==null&&right==null) return true;
        if(left==null||right==null||left.val!=right.val) return false;

        return core(left.left,right.right)&&core(left.right,right.left);
        
    }
}

29 顺时针打印矩阵

LeetCode地址
题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if(matrix==null) return null;
        int [] ret=new int[matrix.length];
        if(matrix.length<1) return ret;

        int rowCount=matrix.length;
        int colCount=matrix[0].length;
        ret=new int[rowCount*colCount];
        int index=0;
        int rowStart=0;
        int colStart=0;
        rowCount--;
        colCount--;
        while(index<=matrix.length*matrix[0].length-1){
            index=printCircle(matrix,ret,index,rowStart,colStart,rowCount,colCount);
            rowStart++;
            colStart++;
            rowCount--;
            colCount--;
        }
        return ret;
    }
    //打印一圈
    public int printCircle(int[][] matrix,int[]ret,int index,int rowStart,int colStart,int rowCount,int colCount){
        //如果是一行
        if(rowStart==rowCount){
            for(int i=colStart;i<=colCount;i++){
                ret[index++]=matrix[rowStart][i];
            }
            return index;
        }//如果是一列
        if(colStart==colCount){
            for(int i=rowStart;i<=rowCount;i++){
                ret[index++]=matrix[i][colCount];
            }
            return index;
        }
        //从左到右打印一行
        for(int i=colStart;i<=colCount;i++){
            ret[index++]=matrix[rowStart][i];
        }
        //从上到下打印一列
        for(int i=rowStart+1;i<=rowCount;i++){
            ret[index++]=matrix[i][colCount];
        }
        //从右向左打印一行
        for(int i=colCount-1;i>=colStart;i--){
            ret[index++]=matrix[rowCount][i];
        }
        //从下到上打印一列
        for(int i=rowCount-1;i>rowStart;i--){
            ret[index++]=matrix[i][colStart];
        }
        return index;
    }
}

30 包含min函数的栈(辅助栈)

LeetCode地址

题目描述:
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

import java.util.Stack;
class MinStack {

    /** initialize your data structure here. */
    Stack<Integer> stack;
    Stack<Integer> minstack;
    public MinStack() {
        stack=new Stack<>();
        minstack=new Stack<>();
    }
    
    public void push(int x) {
        stack.push(x);
        if(minstack.isEmpty()){
            minstack.push(x);
            return;
        }
        if(x<minstack.peek()){
            minstack.push(x);
        }else{
            minstack.push(minstack.peek());
        }
    }
    
    public void pop() {
        if(stack.isEmpty()) return;
        else{
            stack.pop();
            minstack.pop();
        }
    }
    public int top() {
        if(stack.isEmpty()){
            return -1;
        }else{
            return stack.peek();
        }
        
    }
    
    public int min() {
        if(stack.isEmpty()) return -1;
        return minstack.peek();
    }
}

31 栈的压入、弹出序列(辅助栈)

面试题31. 栈的压入、弹出序列 LeetCode 地址
题目描述:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
思路:用辅助栈进行压入、弹出

import java.util.Stack;
class Solution {
    public boolean validateStackSequences(int[] pushed, int[] popped) {
        if(pushed==null||popped==null) return false;
        Stack<Integer> stack=new Stack<>();
        int index=0;
        int point=0;
        while(index<popped.length){
            if(point<pushed.length){
                stack.push(pushed[point++]);
            }else{
                break;
            }
            while(index<popped.length&&!stack.isEmpty()&&popped[index]==stack.peek()){
                stack.pop();
                index++;
            }
        }
        while(index<popped.length&&!stack.isEmpty()&&popped[index]==stack.peek()){
                stack.pop();
                index++;
        }
        if(stack.isEmpty()){
            return true;
        }
        return false;

    }
}

32 I 从上到下打印二叉树(队列)

面试题32 - I. 从上到下打印二叉树
题目描述:从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

import java.util.*;
class Solution {
    public int[] levelOrder(TreeNode root) {
        int []ret=new int[0];
        if(root==null) return ret;
        Queue<TreeNode> queue=new LinkedList<TreeNode>();
        ArrayList<Integer> list=new ArrayList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode node=queue.poll();
            list.add(node.val);
            if(node.left!=null) queue.add(node.left);
            if(node.right!=null) queue.add(node.right);
            
        }
        ret=new int[list.size()];
        for(int i=0;i<list.size();i++){
            ret[i]=list.get(i);
        }
        return ret;
        
    }
}

相关题目: 广度优先遍历图也是用队列

32 II 从上到下打印二叉树(队列)

LeetCode地址

题目描述:从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

import java.util.*;
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret=new ArrayList<>();
        if(root==null) return ret;
        Queue<TreeNode> queue=new LinkedList<TreeNode>();
        queue.add(root);
        while(!queue.isEmpty()){
            int len=queue.size();
            ArrayList<Integer> list=new ArrayList<>();
            while(len-->0){
                TreeNode node=queue.poll();
                list.add(node.val);
                if(node.left!=null) queue.add(node.left);
                if(node.right!=null) queue.add(node.right);
            }
            ret.add(list);
        }
        return ret;
    }
}

32 III 之字形打印二叉树(两个栈)

面试题32 - III. 从上到下打印二叉树 III

import java.util.*;
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret=new ArrayList<>();
        if(root==null) return ret;
        Stack<TreeNode> stack1=new Stack<>();//存从左往右的
        stack1.push(root);
        Stack<TreeNode> stack2=new Stack<>();//存从右往左的
        while(!stack1.isEmpty()||!stack2.isEmpty()){
            ArrayList<Integer> list=new ArrayList<>();
            if(!stack1.isEmpty()){
                while(!stack1.isEmpty()){
                    TreeNode node=stack1.pop();
                    list.add(node.val);
                    if(node.left!=null)  stack2.push(node.left);
                    if(node.right!=null) stack2.push(node.right); 
                }
            }else{
                while(!stack2.isEmpty()){
                    TreeNode node=stack2.pop();
                    list.add(node.val);
                    if(node.right!=null) stack1.push(node.right); 
                    if(node.left!=null)  stack1.push(node.left);
                }
            }
            ret.add(list);
        }
        return ret;
    }
}

33 二叉搜索树的后序遍历序列(递归)

面试题33. 二叉搜索树的后序遍历序列

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        if(postorder==null||postorder.length<1) return true;
        return verifyCore(postorder,0,postorder.length-1);
    }
    public boolean verifyCore(int[] post,int start,int end){
        if(start==end) return true;
        int root=post[end];
        int mid=-1;
        for(int i=start;i<end;i++){
            if(post[i]>root){
                mid=i;
                break;
            }
        }
        //判断是否后面的都大于root
        if(mid!=-1){
            for(int i=mid;i<end;i++){
                if(post[i]>root){
                    continue;
                }else{
                    return false;
                }
            }
        }
        
        if(mid==start) //没有左子树
            return verifyCore(post,mid,end-1);
        if(mid==-1) //没有右子树
            return verifyCore(post,start,end-1);

        return verifyCore(post,start,mid-1)&&verifyCore(post,mid,end-1);
    }
}

相关题目: 判断是否是前序遍历结果

34 二叉树中和为某一值的路径(回溯)

面试题34. 二叉树中和为某一值的路径


import java.util.*;
class Solution {
    List<List<Integer>> ret=new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        if(root==null) return ret;
        ArrayList<Integer> list=new ArrayList<>();
        list.add(root.val);
        core(root,list,sum-root.val);
        return ret;
    }
    public void core(TreeNode node,ArrayList<Integer> list,int sum){
        if(node==null) return;
        if(node.left==null&&node.right==null){
            if(sum==0){
                ret.add(new ArrayList(list));
                return;
            }else{
                return;
            }
        }
        if(node.left!=null){
            list.add(node.left.val);
            core(node.left,list,sum-node.left.val);
            list.remove(list.size()-1);
        }
        if(node.right!=null){
            list.add(node.right.val);
            core(node.right,list,sum-node.right.val);
            list.remove(list.size()-1);
        }
        
    }

}

35 复杂链表的复制

面试题35. 复杂链表的复制

class Solution {
    public Node copyRandomList(Node head) {
        if(head==null) return null;
        Node pHead=head;
        Node pre=head;
        //复制一份连起来  1 1 2 2 3 3
        while(head!=null){
            Node node=new Node(head.val);
            pre=head;
            head=head.next;
            pre.next=node;
            node.next=head;
        }
        //复制随机节点
        head=pHead;
        Node node=head.next;
        while(head!=null){
            node=head.next;
            if(head.random==null){
                node.random=null;
            }else{
                node.random=head.random.next;
            }
            head=node.next;
        }
        //拆分
        head=pHead;
        Node top=head.next;
        node=head.next;
        while(node.next!=null){
            head.next=node.next;
            head=head.next;
            node.next=head.next;
            node=node.next;
        }
        head.next=null;
        head=pHead;
        return top;

    }
}

36 二叉搜索树与双向链表

LeetCode 面试题36. 二叉搜索树与双向(循环)链表
牛客网 双向链表

注意:LeetCode上要求是双向循环链表!!


class Solution {
    public Node core(Node root) {
		if(root==null||(root.left==null&&root.right==null)) return root;
        if(root.left==null&&root.right!=null){
            Node rightLeft=core(root.right);
            rightLeft.left=root;
            root.right=rightLeft;
            return root;
        }
		//左子树最左边的节点
        Node left=core(root.left);
        Node leftRight=left;
        //左子树最右边的节点
        while(leftRight.right!=null){
            leftRight=leftRight.right;
        }
        //右子树最左边的节点
        Node right=core(root.right);
        if(right==null){
            
            root.left=leftRight;
            leftRight.right=root;
            return left;
        }
        root.left=leftRight;
        root.right=right;
        leftRight.right=root;
        right.left=root;
        
        return left;
	}
	 public Node treeToDoublyList(Node root) {
	        if(root==null) return root;
	        if(root.left==null&&root.right==null){
                root.left=root;
                root.right=root;
                return root;
            }
	        if(root.left==null&&root.right!=null){
	            Node rightLeft=core(root);
	            //加上首尾循环
	            Node rightRight=rightLeft;
	            while(rightRight.right!=null){
	                rightRight=rightRight.right;
	            }
	            rightRight.right=root;
	            root.left=rightRight;
	            return root;
	        }
	        Node left=core(root);
	        Node rightRight=root;
	        while(rightRight.right!=null){
	                rightRight=rightRight.right;
	        }
	        //加上首尾循环
	        rightRight.right=left;
	        left.left=rightRight;      
	        return left;  
	    }

}

37 序列化二叉树(递归)

面试题37. 序列化二叉树

public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        //序列化成前序遍历结果
        //null用*表示  用.间隔
        String str="";
        if(root==null) return "*,";
        str+=root.val+",";
        String strLeft=serialize(root.left);
        String strRight=serialize(root.right);
        str=str+strLeft+strRight;
        return str;
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        String [] cs=data.substring(0,data.length()-1).split(",");
        int index[]=new int[1];
        index[0]=0;
        return core(cs,index);
    }
    public TreeNode core(String [] cs,int[]index) {
        if(cs[index[0]].equals("*")){
            index[0]++;
            return null;
        }else{
            TreeNode root=new TreeNode(Integer.valueOf(cs[index[0]]));
            index[0]++;
            root.left=core(cs,index);
            root.right=core(cs,index);
            return root;
        }
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

38 字符串的排列(回溯)

面试题38. 字符串的排列

import java.util.*;
class Solution {
    List<String> list=new LinkedList<>();
    char[] c;
    public void core(int x){
        if(x==c.length-1){
            list.add(String.valueOf(c));
            return;
        }
        HashSet<Character> set=new HashSet<>();

        for(int i=x;i<c.length;i++){
            if(set.contains(c[i])) continue;
            set.add(c[i]);
            swap(i,x);//c[i] 固定在第 x 位 
            core(x+1);
            swap(i,x);
        }
    }
    public void swap(int x,int y){
        char tmp=c[x];
        c[x]=c[y];
        c[y]=tmp;
    }
    public String[] permutation(String s) {
        c=s.toCharArray();
        core(0);
        return list.toArray(new String[list.size()]);    
    }

}

相关题目:
(1)求字符的所有组合
(2)8个数字放到正方体8个顶点上,使得相对面上顶点和相等
(3)8皇后问题

39 数组中出现次数超过一半的数字

面试题39. 数组中出现次数超过一半的数字

class Solution {
    public int majorityElement(int[] nums) {
        if(nums==null||nums.length<1) return -1;
        int count=0;
        int num=nums[0];
        for(int i=0;i<nums.length;i++){
            if(count==0){
                num=nums[i];
                count++;
            }else{
                if(nums[i]==num){
                    count++;
                }else{
                    count--;
                }
            }
        }
        return num;
    }
}

40 最小的k个数 (快排/堆)

面试题40. 最小的k个数
方法一:快排思想

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] ret=new int[k];
        if(arr==null||arr.length<1) return ret;
        quikSort(arr,0,arr.length-1,k);
        for(int i=0;i<ret.length;i++){
            ret[i]=arr[i];
        }
        return ret;
    }
    public void quikSort(int[] arr,int start,int end,int k){
        if(start==end) return ;
        int low=start;
        int high=end;
        int stand=arr[start];
        while(low<high){
            while(low<high&&stand<=arr[high]) 
                high--;
            arr[low]=arr[high];
            while(low<high&&arr[low]<=stand) 
                low++;
            arr[high]=arr[low];
        }
        arr[low]=stand;
        if(low==k){
            return;
        }else if(low<k){
            quikSort(arr,low+1,end,k);
            return;
        }else{
            quikSort(arr,start,low,k);
            return;
        }
        
        
    }
}

方法二:堆

    public int[] getLeastNumbers(int[] arr, int k) {
        int[] ret=new int[k];
        if(arr==null||arr.length<1||k<1) return ret;
        //大顶堆
        PriorityQueue<Integer> heap=new PriorityQueue<>(k,new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2-o1;
			}
		});
        for(int i=0;i<arr.length;i++){
            if(heap.size()<k){
                heap.offer(arr[i]);
            }else{
                if(arr[i]<heap.peek()){
                    //heap.poll();
                	heap.remove();
                    heap.offer(arr[i]);
                }
            }
        }
        int index=0;
        while(!heap.isEmpty()){
            ret[index++]=heap.poll();
        }
        return ret;
    }

41 数据流中的中位数(堆)

面试题41. 数据流中的中位数

import java.util.PriorityQueue;
class MedianFinder {

    /** initialize your data structure here. */
    PriorityQueue<Integer> maxHeap;
    PriorityQueue<Integer> minHeap;
    public MedianFinder() {
        maxHeap=new PriorityQueue<>(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2-o1;
			}
		});
        minHeap=new PriorityQueue<>();//默认小顶堆
    }
    
    public void addNum(int num) {
        //1.保证最小堆比最大堆数多1/0
        //2.保证最小堆的数都大于最大堆的对顶
        if(maxHeap.size()<minHeap.size()){//总数奇数
            if(minHeap.peek()<num){
                minHeap.offer(num);
                maxHeap.offer(minHeap.poll());
            }else{
                maxHeap.offer(num);
            } 
        }else{
            if(!maxHeap.isEmpty()&&num<maxHeap.peek()){//num比最大堆的堆顶小
                maxHeap.offer(num);
                minHeap.offer(maxHeap.poll());
            }else{
                minHeap.offer(num);
            }
        }
    }
    
    public double findMedian() {
        if(minHeap.isEmpty()) return -1.0;//没有数据的情况
        if(maxHeap.size()<minHeap.size()){//总数是奇数
            return minHeap.peek();
        }else{//总数是偶数
            return (maxHeap.peek()+minHeap.peek())/2.0;
        }
    }
}

42 连续子数组的最大和

面试题42. 连续子数组的最大和

class Solution {
    public int maxSubArray(int[] nums) {
        if(nums==null||nums.length<1) return -1;
        int ret=nums[0];
        int num=0;
        for(int i=0;i<nums.length;i++){
            if(num<=0){//加了前面的数小于0,不如不加,从当前数开始
                num=nums[i];
            }else{
                num+=nums[i];
            }
            if(ret<num){
                ret=num;
            }
        }
        return ret;
    }
}

43 1~n整数中1出现的次数

面试题43. 1~n整数中1出现的次数

class Solution {
    public int countDigitOne(int n) {
        if(n<=0) return 0;
        String s=String.valueOf(n);
        return core(s,n);
    }
    public int core(String s,int n){
        if(s==null||s.length()<1)return 0;
        int first=Integer.valueOf(String.valueOf(s.charAt(0)));
        if(first==0) return 0;
        if(s.length()==1&&first>0) return 1;
        //21345 numFirst是万位数目
        int numFirst=0;
        if(first>1)
            numFirst=(int)Math.pow(10,s.length()-1);
        else numFirst=(n%(int)Math.pow(10,s.length()-1))+1;
        //numOther是除了万位之外的1的数目
        int numOther=first*(s.length()-1)*(int)Math.pow(10,s.length()-2);
        //numRest 是1-1345中的数目
        int numRest=core(String.valueOf(n%(int)Math.pow(10,s.length()-1)),n%(int)Math.pow(10,s.length()-1));
        return numFirst+numOther+numRest;
    }
}

44 数字序列中某一位的数字

面试题44. 数字序列中某一位的数字

class Solution {
	public int findNthDigit(int n) {
		long nn=n;
        int digit=1;
        while(true){
            long nums=coreNums(digit);//digit位数占多少位
            if(nn>nums){
            	nn=nn-nums;
            }else{
            	n=(int) nn;
                //n=811 digit=3
                int tmp=n/digit;//270
                int ys=n%digit;//1
                int base=(int)Math.pow(10,digit-1);//100
                if(digit==1) base=0;
                int num=base+tmp;//370
                int ret=Integer.valueOf(String.valueOf(String.valueOf(num).charAt(ys)));
                return ret;
            }
            digit++;
        }
        //return -1;
    }
    public long coreNums(int digit){
    	if(digit==1)  return ((int)Math.pow(10,digit)-0)*digit;
        return ((long)Math.pow(10,digit)-(long)Math.pow(10,digit-1))*digit;
    }
}

45 把数组排成最小的数(排序规则)

面试题45. 把数组排成最小的数


class Solution {
    public String minNumber(int[] nums) {
		ArrayList<String> list =new ArrayList<>();
		for (int i = 0; i < nums.length; i++) {
			list.add(String.valueOf(nums[i]));
		}
		Collections.sort(list,new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				String opt1=o1+o2;
				String opt2=o2+o1;
				if(opt1.equals(opt2)) return 0;
				int len=(o1+o2).length();
				boolean flag=false;
				for(int i=0;i<len;i++){
					if(opt1.charAt(i)<opt2.charAt(i)){
						flag=true;
						break;
					}else if(opt1.charAt(i)>opt2.charAt(i)){
						flag=false;
						break;
					}
				}
				if(flag){
					return -1;
				}else{
					return 1;
				}
				
			}
		});
		StringBuilder ret=new StringBuilder();
		for (int i = 0; i < list.size(); i++) {
			ret.append(list.get(i));
		}
		return ret.toString();
    }
}

46 把数字翻译成字符串(动归)

面试题46. 把数字翻译成字符串

class Solution {
    public int translateNum(int num) {
        String string=String.valueOf(num);
        int dp[]=new int[string.length()+1];
        dp[0]=1;
        for (int i = 1; i <= string.length(); i++) {
        	int tmpRet=dp[i-1];
        	if(i-2>=0){
        		int tmp=Integer.valueOf(string.substring(i-2,i));
    			if (10<=tmp&&tmp<=25) {
    				tmpRet+=dp[i-2];
    			}
        	}
			dp[i]=tmpRet;
		}
        return dp[string.length()];
    }
}

47 礼物的最大价值(动归)

面试题47. 礼物的最大价值
方法一:二维动归

class Solution {
    public int maxValue(int[][] grid) {
        int[][]dp=new int[grid.length][grid[0].length];
        for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < dp[0].length; j++) {
				int opt1=0;
				int opt2=0;
				if(i-1>=0){
					opt1=dp[i-1][j];
				}
				if(j-1>=0){
					opt2=dp[i][j-1];
				}
				dp[i][j]=Math.max(opt1,opt2)+grid[i][j];
			}
		}
        return dp[grid.length-1][grid[0].length-1];
    }
}

方法二:优化,一维动归

class Solution {
    public int maxValue(int[][] grid) {
        int[]dp=new int[grid[0].length];
        for (int i = 0; i < grid.length; i++) {
			for (int j = 0; j < grid[0].length; j++) {
				int opt1=0;
				int opt2=0;
				if(i-1>=0){
					opt1=dp[j];
				}
				if(j-1>=0){
					opt2=dp[j-1];
				}
				dp[j]=Math.max(opt1,opt2)+grid[i][j];
			}
			
		}
        return dp[grid[0].length-1];
    }
}

48 最长不含重复字符的子字符串(动归)

面试题48. 最长不含重复字符的子字符串

class Solution {
	public int lengthOfLongestSubstring(String s) {
		StringBuilder str=new StringBuilder("");
		int len=0;//存之前的值
		int ret=0;//存结果,最长的长度
		int fromIndex=0;//存上一个字符的index
        for (int i = 0; i < s.length(); i++) {
        	String string=String.valueOf(s.charAt(i));
			int index=str.indexOf(string);
			if(index==-1){//不存在
				str.append(string);
				len=str.length();
			}else{//存在该字符
				int index1=s.indexOf(s.charAt(i), fromIndex);
				if(i-index1<=len){//判断上一个当前字符与当前字符之间的距离
					str=new StringBuilder(s.substring(index1+1,i+1));
					len=str.length();
					fromIndex=index1+1;
				}
			}
			ret=Math.max(ret, len);
		}
        return ret;
    }
}

49 丑数

面试题49. 丑数

class Solution {
    public int nthUglyNumber(int n) {
        if(n<=0) return 0;
        int[] ret=new int[n];
        int index=1;
        ret[0]=1;
        int t2=0;
        int t3=0;
        int t5=0;
        while(index<n){
        	int two=ret[t2]*2;
        	int three=ret[t3]*3;
        	int five=ret[t5]*5;
        	//找到最小的 加进去 t++
        	if(two<=three&&two<=five){
        		ret[index++]=two;
        		t2++;
        		if(two==three) t3++;
        		if(two==five)  t5++;
                
        		continue;
        	}
        	if(three<=two&&three<=five){
        		ret[index++]=three;
        		t3++;
        		if(two==three) t2++;
        		if(three==five)  t5++;
        		continue;
        	}
        	if(five<=two&&five<=three){
        		ret[index++]=five;
        		t5++;
        		if(five==three) t3++;
        		if(two==five)  t2++;
        		continue;
        	}
        	
        }
        return ret[n-1];
    }
}

50 第一个只出现一次的字符(Hash)

面试题50. 第一个只出现一次的字符

class Solution {
    public char firstUniqChar(String s) {
        int ret[]=new int[256];//存次数的数组
        for(int i=0;i<s.length();i++){
            ret[s.charAt(i)]+=1;
        }
        for(int i=0;i<s.length();i++){
            if(ret[s.charAt(i)]==1){
                return s.charAt(i);
            }
        }
        return ' ';
    }
}

相关题目:
(1)数据流中的一个只出现的字符
(2)是否是变位词
(3)从第一个字符串中删除第二个字符串中的字母

51 数组中的逆序对(归并)

LeetCode地址

题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

class Solution {
    public int reversePairs(int[] nums) {
        return  mergeSort(nums,0,nums.length-1);
    }
    public int mergeSort(int[]nums,int left,int right){
        if(left>=right) return 0;
        int mid=(left+right)>>1;
        int leftcount=mergeSort(nums,left,mid);
        int rightcount=mergeSort(nums,mid+1,right);
        int mergecount=merge(nums,left,right);
        return leftcount+rightcount+mergecount;
    }
    public int merge(int nums[],int left,int right){
        int count=0,index=0;
        int []tmp=new int[right-left+1];
        int start=left;
        int mid=(left+right)>>1;
        int end=mid+1;
        while(start<=mid&&end<=right){
            if(nums[start]<=nums[end])
                tmp[index++]=nums[start++]; 
            else{
                tmp[index++]=nums[end++];
                count+=mid-start+1;
            }
        }
        while(start<=mid) tmp[index++]=nums[start++];
        while(end<=right) tmp[index++]=nums[end++];
        for(int i=0;i<tmp.length;i++)
            nums[i+left]=tmp[i];
        return count;
    }
}

52 两个链表的第一个公共节点

面试题52. 两个链表的第一个公共节点

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //找出len相差多少
        ListNode nodeA=headA;
        ListNode nodeB=headB;
        int lenA=0;
        int lenB=0;
        while(nodeA!=null){
            nodeA=nodeA.next;
            lenA++;
        }
        while(nodeB!=null){
            nodeB=nodeB.next;
            lenB++;
        }
        int lenTmp=0;
        if(lenA>lenB){
            nodeA=headA;
            nodeB=headB;
            lenTmp=lenA-lenB;
        }else{
            nodeA=headB;
            nodeB=headA;
            lenTmp=lenB-lenA;
        }
        //其中一个先走
        while(lenTmp>0){
            nodeA=nodeA.next;
            lenTmp--;
        }
        //一起遍历
        while(nodeA!=nodeB){
            nodeA=nodeA.next;
            nodeB=nodeB.next;
        }
        return nodeA;
    }
}

53 I 在排序数组中查找数字(二分)

面试题53 - I. 在排序数组中查找数字 I

class Solution {
    public int search(int[] nums, int target) {
        //logn的复杂度
        int leftIndex=0;
        int start=0;
        int end=nums.length-1;
        int mid;
        //找左侧边界
        while(start<=end){
            mid=(start+end)>>1;
            if(nums[mid]==target){
                end=mid-1;
            }else if(nums[mid]<target){
                start=mid+1;
            }else{
                end=mid-1;
            }
        }
        if(start>=nums.length||nums[start]!=target)
            return 0;
        else leftIndex=start;
        //找右侧边界
        start=0;
        end=nums.length-1;
        while(start<=end){
            mid=(start+end)>>1;
            if(nums[mid]==target){
                start=mid+1;
            }else if(nums[mid]<target){
                start=mid+1;
            }else{
                end=mid-1;
            }
        }
        return end-leftIndex+1;
    }
}

53 II 0~n-1中缺失的数字(二分)

面试题53 - II. 0~n-1中缺失的数字

class Solution {
    public int missingNumber(int[] nums) {
        //找到下标和值不相等的元素
        int start=0;
        int end=nums.length-1;
        int mid;
        while(start<=end){
            mid=(start+end)>>1;
            if(nums[mid]!=mid){
                end=mid-1;
            }else{
                start=mid+1;
            }
        }
        return start;
    }
}

53III 数组中数值和下标相等的元素(二分)

题目描述:假设一个单调递增的数组里的每个元素都是整数并且是唯一的。请编程实现一个函数,找出数组中任意一个数值等于其下标的元素。例如,在数组{-3,-1,1,3,5}中,数字3和它的下标相等。

	public int findSameNumber(int[] nums) {
        //找到下标和值相等的元素
        int start=0;
        int end=nums.length-1;
        int mid;
        while(start<=end){
            mid=(start+end)>>1;
            if(nums[mid]==mid){
                return mid;
            }else if(nums[mid]<mid){
                start=mid+1;
            }else{
            	end=mid-1;
            }
        }
        return -1;

54 二叉搜索树的第k大节点(栈)

面试题54. 二叉搜索树的第k大节点


import java.util.Stack;
class Solution {
    public int kthLargest(TreeNode root, int k) {
        if(root==null||k<=0) return -1;
        //非递归中序遍历 左根右,本题需要右根左
        int len=0;
        Stack<TreeNode> stack=new Stack<>();
        TreeNode node=root;
        while(!stack.isEmpty()||node!=null){
            if(node!=null){
                stack.push(node);
                node=node.right;
            }else{
                len++;
                if(len==k){
                    return stack.peek().val;
                }
                node=stack.pop().left;
            }
        }
        return -1;
    }
}

55 I 二叉树的深度

面试题55 - I. 二叉树的深度

class Solution {
    public int maxDepth(TreeNode root) {
        if(root==null) return 0;
        return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }
}

55 II 平衡二叉树

面试题55 - II. 平衡二叉树

方法一:需要重复遍历多次

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null) return true;
        int tmp=Math.abs(depth(root.left)-depth(root.right));
        if(tmp<=1){
            return isBalanced(root.left)&&isBalanced(root.right);
        }else{
            return false;
        }
    }
    public int depth(TreeNode root){
        if(root==null) return 0;
        return Math.max(depth(root.left),depth(root.right))+1;
    }
}

方法二:遍历一次

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null) return true;
        int[]deep=new int[1];
        deep[0]=0;
        return isBalanced(root,deep);
    }
    public boolean isBalanced(TreeNode root,int[] deep) {
        if(root==null){
            deep[0]=0;
            return true;
        }
        int[]left=new int[1];
        int[]right=new int[1];
        if(isBalanced(root.left,left)&&isBalanced(root.right,right)){
            if(Math.abs(left[0]-right[0])<=1){
                deep[0]=Math.max(left[0],right[0])+1;
                return true;
            }
        }
        return false;
    }

}

56 数组中数字出现的次数(异或)

LeetCode地址
题目描述
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
思路:异或
(1)思考数组中有一个出现一次的数字。解决办法是全部异或,因为异或的性质是相同为0,不同为1,某数与自己异或等于0,0与某数异或等于某数。
(2)在有两个出现一次的数字异或之后,得到a b异或的结果;a b异或的结果一定不为0,因为a b不同,找到不同的那个位;再对数组异或,分别得到a 和b
代码

class Solution {
    public int[] singleNumbers(int[] nums) {
        int ret[]=new int[2];
        if(nums.length<=1) return ret;
        //找a b异或之后的结果 mask
        int mask=0;
        for(int num:nums){
            mask=mask^num;
        }
        //找mask位,第一个为1的位
        int bitMask=1;
        while((bitMask&mask)==0){
            bitMask=bitMask<<1;
        }
        //找a b       
        int ret1=0,ret2=0;
        for(int i=0;i<nums.length;i++){
            if((bitMask&nums[i])==0) ret1=ret1^nums[i];
            else ret2=ret2^nums[i];
        }
        ret[0]=ret1;
        ret[1]=ret2;
        return ret;
    }
}

56 II 数组中数字出现的次数 (位运算)

面试题56 - II. 数组中数字出现的次数 II

class Solution {
    public int singleNumber(int[] nums) {
        int []arr=new int[32];//存每一位的和
        int bitMask=1;
        for (int i = 0; i < nums.length; i++) {
        	bitMask=1;
			for (int j = arr.length-1; j >=0 ; j--) {
				if((bitMask&nums[i])==bitMask)
					arr[j]+=1;
				bitMask=bitMask<<1;
			}
		}
        int ret=0;
        int base=1;
        for (int i = arr.length-1; i >=0; i--) {
			if(arr[i]%3!=0){
				ret+=base;
			}
			base=base*2;
		}
        return ret;

    }
}

57 和为s的两个数字(双指针)

面试题57. 和为s的两个数字

class Solution {
    public int[] twoSum(int[] nums, int target) {
    	int []ret=new int[2];
        int start=0;
        int end=nums.length-1;
        while(start<end){
        	if(nums[start]+nums[end]==target){
        		ret[0]=nums[start];
        		ret[1]=nums[end];
                return ret;
        	}else if(nums[start]+nums[end]<target){
        		start++;
        	}else{
        		end--;
        	}
        }
        return ret;
    }
}

57 II 和为s的连续正数序列(双指针)

面试题57 - II. 和为s的连续正数序列

class Solution {
    public int[][] findContinuousSequence(int target) {
        ArrayList<int[]> list=new ArrayList<>();	
        int start=1;
        int end=2;
        int sum=3;
        while(start<end){
        	if (sum==target) {
        		int arr[]=new int[end-start+1];
				for (int i = start; i <= end; i++) 
					arr[i-start]=i;
				list.add(arr);
				end++;
				sum+=end;
			}else if(sum<target){
				end++;
				sum+=end;
			}else{
				sum-=start;
				start++;
				
			}
        }
        int[][] ret=list.toArray(new int[list.size()][]);
        return ret;
    }
}

58 I 翻转单词顺序

面试题58 - I. 翻转单词顺序

class Solution {
    public String reverseWords(String s) {
    	StringBuilder sb=new StringBuilder("");
    	String string=reverse(s);
    	int index=0;
    	char []arr=string.toCharArray();
    	for (int i = 0; i < string.length(); i++) {
    		if(arr[i]!=' '){
    			continue;
    		}else{//不属于字母
    			String tmp=reverse(string.substring(index,i));
    			tmp=tmp.trim();
    			if (!tmp.equals("")) {//处理空格
    				sb.append(tmp);
            		sb.append(arr[i]);
            		index=i+1;
				}
    		}
		}
    	sb.append(reverse(string.substring(index,string.length())));
    	return sb.toString().trim();
    }
    public String reverse(String s) {
    	char[] array=s.toCharArray();
    	int start=0;
    	int end=array.length-1;
    	while(start<end){
    		//swap
    		char tmp=array[start];
    		array[start]=array[end];
    		array[end]=tmp;
    		start++;
    		end--;
    	}
		return String.valueOf(array);
	}
}

58 II 左旋转字符串

面试题58 - II. 左旋转字符串

class Solution {
    public String reverseLeftWords(String s, int n) {
        if(s==null||n<0||s.length()<n) return s;
        String ret="";
        //分别翻转
        String opt1=reverse(s.substring(0,n));
        String opt2=reverse(s.substring(n));
        //翻转整个
        ret=reverse(opt1+opt2);
        return ret;
    }
    public String reverse(String s) {
    	char[] array=s.toCharArray();
    	int start=0;
    	int end=array.length-1;
    	while(start<end){
    		//swap
    		char tmp=array[start];
    		array[start]=array[end];
    		array[end]=tmp;
    		start++;
    		end--;
    	}
		return String.valueOf(array);
	}
}

59 I 滑动窗口的最大值(双端队列)

面试题59 - I. 滑动窗口的最大值

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
    	int[]ret=new int[0];
        if(nums.length<1||k<1) return ret;
        ret=new int[nums.length-k+1];
    	Deque<Integer> queue=new LinkedList<Integer>();
    	//存有可能成为最大值的 数 的 下标
    	for (int i = 0; i < k; i++) {
    		while (!queue.isEmpty()&&nums[queue.getLast()]<=nums[i]) {
    			queue.pollLast();
			}
			queue.addLast(i);
		}
    	int index=0;
    	for (int i = k; i < nums.length; i++) {
			ret[index++]=nums[queue.getFirst()];//first端存最大值
			while (!queue.isEmpty()&&nums[queue.getLast()]<=nums[i]) {
    			queue.pollLast();
			}
			//滑动窗口不包含i数字,已经滑出
			if(!queue.isEmpty()&&queue.getFirst()<=(i-k)){
				queue.pollFirst();
			}
			queue.addLast(i);
		}
    	ret[index++]=nums[queue.getFirst()];
    	return ret;
    }
}

59 II 队列的最大值(双端队列)

面试题59 - II. 队列的最大值

class MaxQueue {
    Deque<Integer> data;
    Deque<Integer> max;
    public MaxQueue() {
        data=new LinkedList<Integer>();
        max=new LinkedList<Integer>();     
    }
    public int max_value() {
        if(!max.isEmpty()) return max.getFirst();
        else return -1;
        
    }
    public void push_back(int value) {
        //加到后面
        while(!max.isEmpty()&&max.getLast()<=value){
            max.pollLast();
        }
        max.addLast(value);
        data.add(value);
    }
    
    public int pop_front() {//删除
        if(data.isEmpty()){
            return -1;
        }else{
            if(data.peek().intValue()==max.getFirst().intValue()){
                max.pollFirst();
            }
            return data.poll();
        }
    }
}

60 n个骰子的点数

面试题60. n个骰子的点数

class Solution {
    public double[] twoSum(int n) {
        int num=6;//注意程序的扩展性
        int lenArr=n*num;
        int sumPre[]=new int[lenArr+1];//存和为i的数量 上一轮
        int sumNow[]=new int[lenArr+1];//存这轮循环 和为i的数量
        int tmp[]=new int[lenArr+1];//
        for (int i = 1; i <= num; i++) {
			sumPre[i]=1;
			sumNow[i]=1;
		}
        for (int i = 2; i <=n; i++) {
        	
        	for (int j = 0; j < sumNow.length; j++) {
        		sumPre[j]=sumNow[j];
				sumNow[j]=0;
			}
			for (int j = i; j <= i*num; j++) {//2..12
				int sum=0;
				int maxlen=num;
				if(j<=6){
					maxlen=j-1;
				}
				for (int k = 1; k <= maxlen; k++) {// 1..6
					sum+=sumPre[j-k];
				}
				sumNow[j]=sum;
			}
		}
        double sumCount=Math.pow(num, n);
        double ret[]=new double[lenArr-n+1];
        int index=0;
        for (int i = n; i <= lenArr; i++) {
			ret[index++]=sumNow[i]/sumCount;
		}
        //Arrays.sort(ret);
        return ret;
    }
}

61 扑克牌中的顺子

面试题61. 扑克牌中的顺子

class Solution {
    public boolean isStraight(int[] nums) {
		//排好序
		Arrays.sort(nums);
		//找数组中0的个数		
		int countZero=0;
		for (int i = 0; i < nums.length; i++) {
			if (nums[i]==0) {
				countZero++;
			}
		}
		//找间隙的个数
		int gap=0;
		for (int i = nums.length-1; i >0; i--) {
            if(nums[i-1]==0){
                break;
            }
			int tmp=nums[i]-nums[i-1];
			if(tmp==0){
				return false;
			}else if(tmp>1){
				gap+=tmp-1;
			}
		}
		if (gap<=countZero) {
			return true;
		}
		return false;
    }
}

62 圆圈中最后剩下的数字

面试题62. 圆圈中最后剩下的数字

class Solution {
    public int lastRemaining(int n, int m) {
        if(n==0||m==0) return -1;
        int last=0;
        for(int i=2;i<=n;i++){
            last=(last+m)%i;
        }
        return last;
    }
}

63 股票的最大利润

面试题63. 股票的最大利润

class Solution {
    public int maxProfit(int[] prices) {
        int minValue=Integer.MAX_VALUE;//之前i-1个数中最小的值
        int ret=0;
        for (int i = 0; i < prices.length; i++) {
        	minValue=Math.min(minValue, prices[i]);
        	ret=Math.max(ret, prices[i]-minValue);
		}
        return ret;
    }
}

64 求1+2+…+n(逻辑运算)

面试题64. 求1+2+…+n

class Solution {
    int ret=0;
    public int sumNums(int n) {
        boolean flag=n>1&& sumNums(n-1)>0;
        ret+=n;
        return ret;
    }
}

65 不用加减乘除做加法(逻辑运算)

面试题65. 不用加减乘除做加法

class Solution {
    public int add(int a, int b) {
        int carry=0;//进位
		int sum=0;//和
		do {
			sum=a^b;
			carry=(a&b)<<1;
			a=sum;
			b=carry;
		} while (carry!=0);
		return sum;
    }
}

66 构建乘积数组

面试题66. 构建乘积数组

class Solution {
    public int[] constructArr(int[] a) {
        int ret[]=new int[a.length];
		int tmp=1;
        for (int i = 0; i < a.length; i++) {
			ret[i]=tmp;
        	tmp*=a[i];
		}
        tmp=1;
        for (int i = ret.length-1; i >=0; i--) {
			ret[i]*=tmp;
			tmp*=a[i];
		}
        return ret;
    }
}

67 把字符串转换成整数(注意考虑情况完整)

面试题67. 把字符串转换成整数

class Solution {
	public int strToInt(String str) {
        if(str==null||str.length()<1) return 0;
		char arr[]=str.trim().toCharArray();
        if(arr.length<1) return 0;
		int sign=1;
		int start=0;
		if (arr[0]=='-') {
			sign =-1;
            start=1;
		}else if (arr[0]=='+') {
			start=1;
		}
		long ret=0;
		for (int i = start; i < arr.length; i++) {
			if (arr[i]<'0'||arr[i]>'9') {
				break;
			}
			ret=ret*10+arr[i]-'0';
			if (ret>Integer.MAX_VALUE) {
				if (sign==1) {
					return Integer.MAX_VALUE;
				}else{
					if ((ret*-1)<=Integer.MIN_VALUE) {
						return Integer.MIN_VALUE;
					}
				}
			}
		}
		return sign*(int)ret;
    }
}

68 I 二叉搜索树的最近公共祖先(递归)

面试题68 - I. 二叉搜索树的最近公共祖先

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==null) return null;
        if(p.val<root.val&&root.val<q.val){
            return root;
        }
        if(p.val<root.val&&q.val<root.val){
            return lowestCommonAncestor(root.left,p,q);
        }
        if(p.val>root.val&&q.val>root.val){
            return lowestCommonAncestor(root.right,p,q);
        }
        return root;
    }
}

68 II 二叉树的最近公共祖先(递归)

面试题68 - II. 二叉树的最近公共祖先

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==null||root.val==p.val||root.val==q.val) return root;
        TreeNode left=lowestCommonAncestor(root.left,p,q);
        TreeNode right=lowestCommonAncestor(root.right,p,q);
        if(left!=null&&right!=null) return root;
        if(left!=null)
            return left;
        else return right;
    }
}

你可能感兴趣的:(《剑指Offer》Java版本 LeetCode)