20220828 华泰证券笔试

综述:其中两道算法+一道mysql题目【没合适的,投递了测开,哈哈哈】全A

算法1

数组中的逆序对【剑指Offer 51. 数组中的逆序对】

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

思路:按照归并排序的思想去处理;

      「归并排序」与「逆序对」是息息相关的。归并排序体现了 “分而治之” 的算法思想,具体为:

        分: 不断将数组从中点位置划分开(即二分法),将整个数组的排序问题转化为子数组的排序问题;
        治: 划分到子数组长度为 1 时,开始向上合并,不断将 较短排序数组 合并为 较长排序数组,直至合并至原数组时完成排序;

        合并阶段 本质上是 合并两个排序数组 的过程,而每当遇到 左子数组当前元素 > 右子数组当前元素 时,意味着 「左子数组当前元素 至 末尾元素」 与 「右子数组当前元素」 构成了若干 「逆序对」 

下面是一个数组归并排序的示例:

class Solution {
    int[] nums, tmp;
    public int reversePairs(int[] nums) {
        this.nums = nums;
        tmp = new int[nums.length];
        return mergeSort(0, nums.length - 1);
    }
    private int mergeSort(int l, int r) {
        // 终止条件
        if (l >= r) return 0;
        // 递归划分
        int m = (l + r) / 2;
        int res = mergeSort(l, m) + mergeSort(m + 1, r);
        // 合并阶段
        int i = l, j = m + 1;
        for (int k = l; k <= r; k++)
            tmp[k] = nums[k];
        for (int k = l; k <= r; k++) {
            if (i == m + 1)
                nums[k] = tmp[j++];
            else if (j == r + 1 || tmp[i] <= tmp[j])
                nums[k] = tmp[i++];
            else {
                nums[k] = tmp[j++];
                res += m - i + 1; // 统计逆序对
            }
        }
        return res;
    }
}

 问题2

问题描述:

有一棵二叉树,树上每个点标有权值,权值各不相同,请设计一个算法算出权值最大的叶节点权值最小的叶节点距离。二叉树每条边的距离为1,一个节点经过多少条边到达另一个节点为这两个节点之间的距离。

思路 来源

思路1:典型的二进制编码题,算出叶子节点二进制编码,再比编码,计算后缀长度和

思路2:先找到最大最小节点位置,在找出最近的公共祖先,在分别计算到公共祖先的距离,在求和,虽然麻烦,但很通俗易懂

代码1



//典型的二进制编码题,算出叶子节点二进制编码,再比编码,计算后缀长度和
import java.util.*;
 
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}*/
 
public class Tree {
    private int max=0;
    private int min=99999;
    private StringBuilder maxcodec;
    private StringBuilder mincodec;
        void PreOrder(TreeNode T,char code,StringBuilder codec){
        if(T!=null){           
            codec.append(code);
            if(T.left==null && T.right==null)
            {
                if(max<T.val)
                {
                    max=T.val;
                    maxcodec = codec;
                }
                 
                if(min>T.val)
                {
                    min=T.val;
                    mincodec = codec;
                }
            }
            PreOrder(T.left,'0',new StringBuilder(codec));
            PreOrder(T.right,'1',new StringBuilder(codec));
        }
    }
    public int getDis(TreeNode root) {
        PreOrder(root,'0',new StringBuilder());
        int index=0;
        for(index=0; index<(maxcodec.length()>mincodec.length()?maxcodec.length():mincodec.length());index++)
        {
            if(maxcodec.charAt(index)!=mincodec.charAt(index))
                break;
        }
        return (maxcodec.substring(index).length()+mincodec.substring(index).length());
     
        // write code here
    }
}

代码2


import java.util.*;
/*
 
public class TreeNode {
 
int val = 0;
 
TreeNode left = null;
 
TreeNode right = null;
 
public TreeNode(int val) {
 
this.val = val;
 
}
 
}*/
 
public class Tree {
 
private TreeNode maxNode = new TreeNode(Integer.MIN_VALUE);
 
private TreeNode minNode = new TreeNode(Integer.MAX_VALUE);
 
 
 
public int getDis(TreeNode root) {
 
    // write code here
 
    getMaxMin(root);//找到最大最小叶子节点
 
    TreeNode lcaNode = getLCA(root);//找LCA
 
    int a = getNodeDis(lcaNode, maxNode);//最大值叶子节点到LCA的距离;
 
    int b = getNodeDis(lcaNode, minNode);//最小值叶子节点到LCA的距离;
 
    return a+b;
 
}
 
 
 
// 先找到最大最小叶子节点
 
public void getMaxMin(TreeNode root) {
 
    if (root == null) {
 
        return;
 
    }
 
    if (root.left == null && root.right == null) {
 
        if (root.val > maxNode.val) {
 
            maxNode = root;
 
        } else if (root.val < minNode.val) {
 
            minNode = root;
 
        }
 
    }
 
    getMaxMin(root.left);
 
    getMaxMin(root.right);
 
}
 
 
 
// LCA最近公共祖先
 
public TreeNode getLCA(TreeNode root) {
 
    if (root == null) {// 说明是空树
 
        return null;
 
    }
 
    if (root.val == maxNode.val || root.val == minNode.val) {// 在当前树的根节点上找到两个节点之一
 
        return root;
 
    }
 
    TreeNode leftNode = getLCA(root.left);// 左子树中的查找两个节点并返回查找结果
 
    TreeNode rightNode = getLCA(root.right);// 右子树中查找两个节点并返回查找结果
 
    if (leftNode == null) {// 左子树中没找到,则一定在右子树上
 
        return rightNode;
 
    } else if (rightNode == null) {// 右子树没找到一定在左子树上
 
        return leftNode;
 
    } else {// 左右子树均找到一个节点,则根节点为最近公共祖先
 
        return root;
 
    }
 
}
 
 
 
//获取叶子节点到LCA距离
 
public int getNodeDis(TreeNode lcaNode, TreeNode node){
 
    if(lcaNode==null){
 
        return -1;
 
    }
 
    if(lcaNode.val==node.val){
 
         return 0;
 
    }
 
    //三种情况:两个均在左子树;两个均在右子树;一左一右,所以不能用if-elseif结构
 
    int distance = getNodeDis(lcaNode.left, node);//左子树未找到两个节点之一
 
    if(distance==-1){
 
        distance = getNodeDis(lcaNode.right, node);
 
    }
 
    if(distance!=-1){
 
        return distance+1;
 
    }
    return -1;
	}
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值