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的主要内容,如果未能解决你的问题,请参考以下文章
剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)