zoukankan      html  css  js  c++  java
  • 路由器, 美团笔试题, 差分

    1. 前缀和与差分及其应用
    有两个数组A和B。

    前缀和数组A:

    (a_1 , a_2, a_3..., a_n)

    差分数组B:

    (b_1, b_2, b_3, ..., b_n)

    数组A和B的关系如下:

    (1)前缀和数组A:

    (a_1 , a_2, a_3..., a_n)又等于

    (b_1, b_1+b_2, b_1+b_2+b_3, ..., b_1+b_2+...+bn)

    (2)差分数组B:

    (b_1, b_2, b_3, ..., b_n) 等于

    (a_1, a_2 - a_1, a_3 - a_2, ..., a_n - a_{n-1})

    前缀和和差分互为逆运算。因此,数组A是数组B的前缀和数组,数组B是数组A的差分数组。

    差分数组的作用:

    我们需要在A数组的某个区间【l,r】上(a[l], a[l+1], ..., a[r])频繁加上或者减去某个数c,一次操作需要对A数组操作r-l+1次,如果频繁操作,时间复杂度较高。但如果在数组A的差分数组上操作只需要(b_l+c), (b_{r+1}-c),再通过数组B重构出A数组,就可以达到在原A数组的区间【l,r】上加上c。简言之,求 a数组【l, r】区间所有数加一个数c, 则只需要 (b_l + c), 和 (b_{r+1} - c),在通过B数组重构A数组,即可以在a数组【l, r】区间所有数加一个数c。

    分析:

    (b_l+c)会影响到(a_l, a_{l+1}, a_n),他们是b数组的前缀和,即(a_l, a_{l+1}, a_n)变成了(a_l+c, a_{l+1}+c, a_n+c)

    (a_{r+1}, a_{r+2}, a_n)同理, (b_{r+1}+c)会影响到(a_{r+1}, a_{r+2}, a_n),他们是数组B的前缀和,即变成(a_{r+1}-c, a_{r+2}-c, a_n-c)了。

    因此, (b_l + c), 和 (b_{r+1} - c)会使得即(a_l, a_{l+1}, a_r)变成了(a_l+c, a_{l+1}+c, a_r+c)

    如果1 <= l, r, <= n,我们由k(1 <= k <= n)次这样的操作,如果在数组A上直接操作,时间复杂度为(O(n^2)), 如果通过构造A的差分数组,每次操作为O(1),K次操作为O(n),最后再通过数组B重新构造出新数组A。

    2. 例题: 路由器, 美团笔试题

    import java.util.*;
    public class Main {
        public static void main(String[] args){
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt(), k = sc.nextInt();
            int[] a = new int[n];
            for(int i=0; i < n; i++) 
                a[i] = sc.nextInt();
            int[] b = new int[n]; //前缀和数组
            int[] c = new int[n]; // 差分数组
            for(int i=0; i < n; i++) {
                int l = Math.max(i-a[i], 0);
                int r = Math.min(i+a[i], n-1);
                c[l] += 1;
                if(r+1 < n) c[r+1] -= 1;
            }
            int res = 0;
            // 通过C数组重构B数组
            for(int i=0; i < n; i++) {
                if(i > 0)
                    b[i] = c[i] + b[i-1];
                else
                    b[0] = c[0];
                if(b[i] >= k) res++;
            }
            System.out.println(res);
        }
    }
    
  • 相关阅读:
    Java 在线/离线 文档
    Java集合框架全解
    【LeetCode】204.计数质数
    深入SpringMvc
    SpringMvc基础
    SSM整合
    Spring注解
    SpringAop编程
    2路插入排序
    Matplotlib绘图库简要介绍
  • 原文地址:https://www.cnblogs.com/lixyuan/p/13184460.html
Copyright © 2011-2022 走看看