微众银行笔试20230903第三题赏析

微众银行笔试/20230903/第三题赏析

在介绍这题前,先介绍lc 560 和为K的子数组

一、和为K的子数组

链接:https://leetcode.cn/problems/subarray-sum-equals-k/description/

给你一个整数数组 nums 和一个整数 k ,请你统计并返回该数组中和为 k 的连续子数组的个数。

(1)暴力解法

回溯法遍历每一个连续子数组,计算子数组的和并与K相比。时间复杂度 O ( N 3 ) O(N^3) O(N3)

这样做显然不行,有优化的地方吗?有。计算子数组的和。

(2)前缀和优化

我们知道前缀和这一技巧,在做一次预处理后,计算某个区间的和只需要O(1)时间。那么题目转化为:求有多少个区间【l,r】和为K,其中l和r范围是0~N-1,且l<r。

具体的解题过程就变成了两层循环:

for(int r=0; r<N; ++r){
	for(int l=0; l<=r; ++l){
		//求l,r区间和
		//判断区间和是否与k相等
	}
}

能不能再优化?

(3)哈希表优化

计算公式: p r e s u m [ j ] − p r e s u m [ i ] = k presum[j] - presum[i] = k presum[j]presum[i]=k ,那么 p r e s u m [ j ] − k = p r e s u m [ i ] presum[j] -k = presum[i] presum[j]k=presum[i]

转换思路:考虑以 j j j为右端点的区间,其区间和为K的个数。这等价于求多少个 i < j i<j i<j,满足 $presum[i] = presum[j] -k $

等等,这个公式有点熟悉?力扣梦开始的地方,力扣第一题,两数之和。这里是两数之差。

接下来的思路就很明朗了,空间换时间,利用哈希宝提前存每个presum[i]。

class Solution {
    public int subarraySum(int[] nums, int k) {
        int N = nums.length;
        int[] preSum = new int[N];
        preSum[0] = nums[0];
        for(int i=1; i<N; ++i){
           preSum[i] = preSum[i-1]+nums[i]; 
        }
        Map<Integer, Integer> map = new HashMap<>();
        map.put(0, 1); // 很重要,对应preSum[-1]=0
        int ans = 0;
        for(int j=0; j<N; ++j){
            if(map.containsKey(preSum[j]-k)) {
                ans += map.get(preSum[j]-k);
            }
            map.put(preSum[j], map.getOrDefault(preSum[j], 0)+1);
        }
        return ans;
    }
}

细节注意:

  • 以往前缀和下标都是不对应的,比如preSum[i+1] 为从0到i得区间和。

这道题的下标是对应的,原因是 map.put(0, 1);

  • map.put(0, 1); 的作用

其实还是前缀和下标对应的问题。当我们要计算第一个区间,即[0,0]的区间和时,我们采用了preSum[0]-0的实现。

二、微众银行第三题-平均值

2.1 题目详情

(1)题目描述

小明有一个数组。他挑选了一个有理数u/v,现在他想知道这个数组有多少个子区间的平均值恰好等于u/v。数组

的子区间即是数组中连续的一段区间,如数组[4,2,6]有6个子区间 [4],[2],[6],[4,2],[2,6],[4,2,6]。

(2)输入描述

第一行有三个整数 n,u,v (1 ≤ n, v ≤ 100000,1 ≤ u ≤ n *v),代表数组的长度,小明选择的有理数的分子和分母。

输入保证u和v的最大公因数是1,即u/v是最简分数。

第二行有n个绝对值不超过1000000的整数,代表数组中的元素。

数字间两两有空格隔开。

(3)输出描述

输出一个非负整数,代表所求的答案。

(4)样例

输入

6 5 2
2 4 1 3 2 3

输出

6

2.2 思路分析

仔细思考,如果将题目描述的中平均值去除,这不就是和为K的子数组吗?

条件给的数组平均值与一个真分数,是想要我们干什么呢?回到判断相等的公式。

p r e s u m [ j ] − p r e s u m [ i ] j − i ] = u v \frac{presum[j]-presum[i]}{j-i]} = \frac{u}{v} ji]presum[j]presum[i]=vu

我们将它变形一下:

u × i − v × p r e s u m [ i ] = u × j − v × p r e s u m [ j ] u\times i - v \times presum[i] = u \times j - v \times presum[j] u×iv×presum[i]=u×jv×presum[j]

等等,这两边的形式好像高度对称啊,我们定义一个新数组 a [ i ] = u × i − v × p r e s u m [ i ] a[i] = u \times i - v \times presum[i] a[i]=u×iv×presum[i],上面公式转化为了

a [ i ] = a [ j ] − 0 a[i] = a[j] - 0 a[i]=a[j]0

这不就是两数之差为k嘛,只不过k为0。兜兜转转,我们又回到了力扣第一题。

2.3 题解

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt(), u = scanner.nextInt(), v = scanner.nextInt();
        int[] a = new int[n];
        int[] psum = new int[n + 1];

        for (int i = 0; i < n; i++) {
            a[i] = scanner.nextInt();
            psum[i + 1] = psum[i] + a[i];
        }

        long rs = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = i; j <= n; j++) {
                if (1L * (psum[j] - psum[i - 1]) * v == 1L * u * (j - i + 1)) {
                    rs++;
                }
            }
        }

        System.out.println(rs);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微众银行通过腾讯的大数据分析,对QQ、微信的用户进行多维度评定。评估的点包括用户的年龄、性别、兴趣爱好等特征以及社交、购物、游戏等行为,同时结合入行征信数据,形成对用户的诚信评级,决定用户可申请贷款的额度。 在微众银行的数据分析笔试中,你可能会面临一些与数据分析相关的问和场景。其中,你可能需要了解如何构建风险模型和应用策略设计。此外,你还需要对互联网反欺诈体系有一定的了解,包括欺诈特征检测、内部欺诈特征识别和外部威胁情报监测等方面的知识。 在笔试中,你可能会被要求解决一些与数据分析和风险控制相关的问,例如如何区分正常行为和欺诈行为、如何利用数据识别欺诈特征等。同时,你还需要了解如何建立综合的反欺诈体系,包括整体规划和协作、欺诈特征识别和外部威胁情报监测等方面的内容。 为了在微众银行的数据分析笔试中取得好的成绩,你可以通过深入了解微众银行的业务模式和数据分析方法,熟悉风险模型和应用策略设计等知识,并掌握互联网反欺诈体系的构成和建设等内容。这样,你就可以更好地应对笔试中的问,并展示出你在数据分析方面的能力和经验。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [微众银行风险模型笔试前做的准备(公司介绍+欺诈与反欺诈+sql+机器学习)](https://blog.csdn.net/weixin_43584807/article/details/105385082)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值