2021-6-7剑指笔记03

Posted 轻舟一曲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-6-7剑指笔记03相关的知识,希望对你有一定的参考价值。

笔记03

_31_不用加减乘除做加法

package LeetCode.笔记03;

public class _31_不用加减乘除做加法 {

    /*
    首先回顾加法三步:7+15
    1.不要进位相加 1 2
    2.做进位10
    3.将前两个结果相加22

    二进制加法:
    1.异或
    2.与
    3.重复前两步
    * */
    public int add(int a, int b) {
       int sum=0;
       int carry=1;
       //进位也有可能是负的
       while (carry!=0){//二进制加法有进位则一直循环
           sum=a^b;
           carry=(a&b)<<1;
           a=sum;
           b=carry;
       }
       return a;

    }


}

_32_缺i构建乘积数组

package LeetCode.笔记03;

public class _32_缺i构建乘积数组 {
    /*
    B[i]=A[0]*A[1]*..A[i-1]*A[i+1]*..A[n-1]
    分成两部分
    1)  C[i]=A[0]*A[1]*..A[i-1]  缺少i的前积和

        C[i]=C[i-1]*A[i-1]

    2)  D[i]=A[i+1]*..A[n-1]  缺少i的后积和

        D[i]=A[i+1]*D[i+1]

    B[i]=C[i]*D[i];

    * */

    public int[] constructArr(int[] a) {
        if (a==null) return null;
        int len=a.length;
        if (len==0||len==1) return new int[]{};

        int[] C=new int[len];
        int[] D=new int[len];
        C[0]=1;
        for (int i=1;i<len;i++){
            C[i]=C[i-1]*a[i-1];
        }
        D[len-1]=1;
        for (int i=len-2;i>=0;i--){
            D[i]=D[i+1]*a[i+1];
        }

        int[] B=new int[len];
        for (int i=0;i<len;i++){
            B[i]=C[i]*D[i];
        }

        return B;
    }

}

_33_把字符串转换成整数

package LeetCode.笔记03;

import org.junit.Test;

public class _33_把字符串转换成整数 {
    //两大经典面试算法题之一
    /*
    需要考虑的问题如下:空指针,空串,正负号,溢出
    * */
    public boolean nullInput=false;
    public boolean validInput=true;
    public int strToInt(String str) {

        if (str==null) {
            nullInput=true;
            return -1;
        }
        if (str.length()==0){
            validInput=false;
            return 0;
        }

        char[] c = str.trim().toCharArray();
        if (c.length==0) return 0;
        int res=0;
        int bnDry=Integer.MAX_VALUE/10;
        int i=1;
        int sign=1;
        if (c[0]=='-') sign=-1;
        else if (c[0]!='+') i=0;
        for (int j=i;j<c.length;j++){
            if (c[j]<'0'||c[j]>'9') break;
            if (res>bnDry||res==bnDry&&c[j]>'7')//2147483647    -2147483648
                return sign==1?Integer.MAX_VALUE:Integer.MIN_VALUE;
            res=res*10+(c[j]-'0');
        }

        return sign*res;
    }

    @Test
    public void test(){
        System.out.println(strToInt("-2147483648"));
    }



}

_34_二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。

package LeetCode.笔记03;

public class _34_二叉搜索树的最近公共祖先 {

    public class TreeNode{
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x){val=x;}
    }

    //另外一种不用递归的方法:先找p , q的路径 然后找分叉点

    public int min=0;
    public int max=0;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

        min=Math.min(p.val,q.val);
        max=Math.max(p.val,q.val);

        TreeNode x=root;
        while (x!=null){
            if (x.val>=min&&x.val<=max) break;
            else if (x.val<min) x=x.right;
            else x=x.left;
        }
        return x;

    }
    public TreeNode lowest(TreeNode root){
        if (root==null) return null;
        else if (root.val>=min&&root.val<=max) return root;
        else if (root.val<min) return lowest(root.right);
        else return lowest(root.left);
    }

}

_35_二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

示例 1:

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2:

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。

package LeetCode.笔记03;

import org.junit.Test;

import java.util.LinkedList;
import java.util.List;

public class _35_二叉树的最近公共祖先 {

    public class TreeNode{
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x){val=x;}
    }


    /*
     1. 当同时为空 :说明子树中都不包含 返回null
     2. 同时不为空 :返回 root
     3. 有一个为空
    * */
    public TreeNode lowestCommonAncestor01(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left == null && right == null) return null; // 1.
        if(left == null) return right; // 3.
        if(right == null) return left; // 4.
        return root; // 2.
    }

    /*
    不使用递归时间效率将有很大提升:BST?有指向父节点指针?
    普通二叉树:先序遍历先找出路径,用两个链表存储,最后找最后一个公共节点
    * */

    public List<TreeNode> path;
    public boolean flag=false;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
         if (root==null) return null;
         path=new LinkedList<>();
         getPath(root,p);
         flag=false;
         List<TreeNode> pPath=path;
         path=new LinkedList<>();
         getPath(root,q);
         List<TreeNode> qPath=path;

         TreeNode x=null;
         int i=0;
         int size=Math.min(pPath.size(),qPath.size());
         while (i<size){
             if (pPath.get(i)!=qPath.get(i)) break;
             x=pPath.get(i);
             i++;
         }
         return x;

    }
    public void getPath(TreeNode root,TreeNode target){
        if (root==null||flag) return;
        if (root==target){
            flag=true;//防止在兄弟节点继续搜索,剪枝
            path.add(root);//最后递归返回会remove
            return;
        }
        path.add(root);
        getPath(root.left,target);
        getPath(root.right,target);
        //如果找到了就不能删最后一个
        if (!flag) path.remove(path.size()-1);
    }

    @Test
    public void test(){
        TreeNode x3=new TreeNode(3);
        TreeNode x5=new TreeNode(5);
        TreeNode x1=new TreeNode(1);
        TreeNode x6=new TreeNode(6);
        TreeNode x2=new TreeNode(2);
        TreeNode x0=new TreeNode(0);
        TreeNode x8=new TreeNode(8);
        TreeNode x7=new TreeNode(7);
        TreeNode x4=new TreeNode(4);

        x3.left=x5;x3.right=x1;
        x5.left=x6;x5.right=x2;
        x1.left=x0;x1.right=x8;
        x2.left=x7;x2.right=x4;

        TreeNode treeNode = lowestCommonAncestor(x3, x5, x1);
        if (treeNode!=null) System.out.println(treeNode.val);
        else System.out.println("null");
    }


}

以上是关于2021-6-7剑指笔记03的主要内容,如果未能解决你的问题,请参考以下文章

2021-6-7剑指笔记02

2021/6/7 刷题笔记青蛙跳台阶问题与合并排序的数组

剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)

剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)

2021-6-7笔记02

2021-6-13-剑指笔记01