欢迎光临
我们一直在努力

华为OD机试真题 新系统【统计盈利目标区间】

统计盈利目标区间(Py/Java/C/C++/Js/Go)题解

华为OD机试新系统真题 华为OD上机考试新系统真题 6月3号 100分题型

华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解

题目内容

某公司的财务流水系统重构为实时流处理架构。日盈利数据(可正可负)作为消息一条条实时推送。 请设计一个实时监控模块,它接收两个序列:操作指令序列

 

o

p

s

\\ ops

 ops 和对应的参数序列

 

v

a

l

s

\\ vals

 vals

  •  

    o

    p

    s

    [

    i

    ]

    \\ ops[i]

     ops[i] == “

    a

    d

    d

    add

    add” 时:代表接收一条新的日盈利流数据,其值为

     

    v

    a

    l

    s

    [

    i

    ]

    \\ vals[i]

     vals[i]

  •  

    o

    p

    s

    [

    i

    ]

    \\ ops[i]

     ops[i] == “

    q

    u

    e

    r

    y

    query

    query” 时:代表发起一次实时查询,目标值为

     

    v

    a

    l

    s

    [

    i

    ]

    \\ vals[i]

     vals[i](即

     

    t

    a

    r

    g

    e

    t

    \\ target

     target)。要求立刻返回:以当前最新到达的这笔流水为区间右端点,且区间总和恰好等于

     

    t

    a

    r

    g

    e

    t

    \\ target

     target 的连续区间个数。

  • 输入描述

    • o

      p

      s

      ops

      ops:字符串数组,表示操作指令序列。

    • v

      a

      l

      s

      vals

      vals:整型数组,表示与

      o

      p

      s

      ops

      ops 一一对应的参数序列。对于

      a

      d

      d

      add

      add 指令,代表盈利值;对于

      q

      u

      e

      r

      y

      query

      query 指令,代表目标值

      t

      a

      r

      g

      e

      t

      target

      target

    输出描述

    返回一个整型数组,按照

    q

    u

    e

    r

    y

    query

    query 指令出现的顺序,依次保存每次查询的结果,如果没有

    q

    u

    e

    r

    y

    query

    query ,返回空数组,如果

    q

    u

    e

    r

    y

    query

    query 没有符合条件的区间,返回

    0

    0

    0

    约束条件

  • o

    p

    s

    ops

    ops 中仅包含"

    a

    d

    d

    add

    add “和”

    q

    u

    e

    r

    y

    query

    query ",

    o

    p

    s

    .

    l

    e

    n

    g

    t

    h

    <

    =

    10

    5

    ops.length <= 10^5

    ops.length<=105

  • 10

    4

    <

    =

    v

    a

    l

    u

    e

    s

    [

    i

    ]

    <

    =

    10

    4

    -10^4 <= values[i] <= 10^4

    104<=values[i]<=104 当操作作为

    a

    d

    d

    add

    add

  • 10

    9

    <

    =

    v

    a

    l

    u

    e

    s

    [

    i

    ]

    <

    =

    10

    9

    -10^9 <= values[i] <= 10^9

    109<=values[i]<=109 当操作作为

    q

    u

    e

    r

    y

    query

    query

  • 用例的输入都是合法的
  • 样例1

    输入

    add,add,query,add,query
    1,2,3,3,6

    输出

    1,1

    说明

    • a

      d

      d

      add

      add

      1

      1

      1:流为

      [

      1

      ]

      [1]

      [1]

    • a

      d

      d

      add

      add

      2

      2

      2:流为

      [

      1

      ,

      2

      ]

      [1,2]

      [1,2]

    • q

      u

      e

      r

      y

      query

      query

      3

      3

      3:最新数据是

      2

      2

      2。以

      2

      2

      2 结尾且和为

      3

      3

      3 的区间只有

      [

      1

      ,

      2

      ]

      [1,2]

      [1,2],返回

      1

      1

      1

    • a

      d

      d

      add

      add

      3

      3

      3:流为

      [

      1

      ,

      2

      ,

      3

      ]

      [1,2,3]

      [1,2,3]

    • q

      u

      e

      r

      y

      query

      query

      6

      6

      6:最新数据是

      3

      3

      3。以

      3

      3

      3 结尾且和为

      6

      6

      6 的区间只有

      [

      1

      ,

      2

      ,

      3

      ]

      [1,2,3]

      [1,2,3],返回

      1

      1

      1

    样例2

    输入

    add,add,add,query,add,add,query
    1,-1,0,0,1,-1,0

    输出

    2,3

    说明

    • 前三次

      a

      d

      d

      add

      add 后,流为

      [

      1

      ,

      1

      ,

      0

      ]

      [1,-1,0]

      [1,1,0]

    • 第一个

      q

      u

      e

      r

      y

      query

      query

      0

      0

      0:以最新元素

      0

      0

      0 结尾,和为

      0

      0

      0 的区间有

      [

      0

      ]

      [0]

      [0]

      [

      1

      ,

      1

      ,

      0

      ]

      [1,-1,0]

      [1,1,0],返回

      2

      2

      2

    • 后两次

      a

      d

      d

      add

      add 后,流为

      [

      1

      ,

      1

      ,

      0

      ,

      1

      ,

      1

      ]

      [1,-1,0,1,-1]

      [1,1,0,1,1]

    • 第二个

      q

      u

      e

      r

      y

      query

      query

      0

      0

      0:以最新元素

      1

      -1

      1 结尾,和为

      0

      0

      0 的区间有

      [

      1

      ,

      1

      ]

      [

      0

      ,

      1

      ,

      1

      ]

      [

      1

      ,

      1

      ,

      0

      ,

      1

      ,

      1

      ]

      [1,-1]、[0,1,-1]、[1,-1,0,1,-1]

      [1,1][0,1,1][1,1,0,1,1],返回

      3

      3

      3

    题解

    思路:前缀和

  • 利用前缀和来解决查询以当前最新到达的这笔流水为区间右端点,且区间总和恰好等于 target 的连续区间个数, 具体逻辑为当前前缀和为prefix, 满足区间的区间数量就为0-i前缀和等于prefix -target的数量。
  • 按照1的逻辑具体处理逻辑如下:
  • 定义prefix保存当前前缀和,使用哈希表或数组保存前缀和出现的数量,定义ans保存查询结果
  • 从前往后遍历输入指定,处理逻辑如下:
    • op = add, 更新prefix += val, 对应前缀和数量 + 1
    • op = query是,查询指定前缀和为prefix – va的数量加入ans
  • ans保存的就是结果。
  • c++

    #include<bits/stdc++.h>
    #include <unordered_map>
    #include <vector>
    using namespace std;

    // 通用 切割函数 函数 将字符串str根据delimiter进行切割
    vector<string> split(const string& str, const string& delimiter) {
    vector<string> result;
    size_t start = 0;
    size_t end = str.find(delimiter);
    while (end != string::npos) {
    result.push_back(str.substr(start, end – start));
    start = end + delimiter.length();
    end = str.find(delimiter, start);
    }
    // 添加最后一个部分
    result.push_back(str.substr(start));
    return result;
    }

    vector<int> handle(vector<string>& ops, vector<int>& value) {
    // 前缀和
    long prefix = 0;
    // 记录指定前缀和出现次数
    unordered_map<long, int> prefixCount;
    int n = ops.size();
    vector<int> ans;
    for (int i = 0; i < n; i++) {
    int val = value[i];
    if (ops[i] == "add") {
    prefix += val;
    // 指定前缀和次数
    prefixCount[prefix]++;
    } else if (ops[i] == "query") {
    long target = prefix – val;
    ans.push_back(prefixCount[target]);
    }
    }
    return ans;
    }

    int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    string opsStr, valueStr;
    getline(cin, opsStr);
    getline(cin, valueStr);
    vector<string> ops = split(opsStr, ",");
    vector<string> valuePart = split(valueStr, ",");
    vector<int> value;
    for (auto str : valuePart) {
    value.push_back(stoi(str));
    }
    vector<int> ans = handle(ops, value);

    // 处理结果
    for (int i = 0; i < ans.size(); i++) {
    if (i != 0) {
    cout << ",";
    }
    cout << ans[i];
    }
    return 0;
    }

    Java

    import java.util.*;

    public class Main {

    static List<Integer> handle(String[] ops, int[] value) {
    // 当前前缀和
    long prefix = 0;
    // 指定前缀和出现数量
    Map<Long, Integer> prefixCount = new HashMap<>();
    List<Integer> ans = new ArrayList<>();

    int n = ops.length;
    for (int i = 0; i < n; i++) {
    int val = value[i];

    if (ops[i].equals("add")) {
    prefix += val;
    prefixCount.put(prefix, prefixCount.getOrDefault(prefix, 0) + 1);
    } else if (ops[i].equals("query")) {
    long target = prefix val;
    ans.add(prefixCount.getOrDefault(target, 0));
    }
    }
    return ans;
    }

    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    String opsStr = sc.nextLine();
    String valueStr = sc.nextLine();

    String[] ops = opsStr.split(",");
    String[] valuePart = valueStr.split(",");

    int[] value = new int[valuePart.length];
    for (int i = 0; i < valuePart.length; i++) {
    value[i] = Integer.parseInt(valuePart[i]);
    }

    List<Integer> ans = handle(ops, value);

    for (int i = 0; i < ans.size(); i++) {
    if (i > 0) System.out.print(",");
    System.out.print(ans.get(i));
    }
    }
    }

    Python

    import sys

    def handle(ops, value):
    # 当前前缀和
    prefix = 0
    # 指定前缀和出现数量
    prefix_count = {}
    ans = []

    for op, val in zip(ops, value):
    if op == "add":
    prefix += val
    prefix_count[prefix] = prefix_count.get(prefix, 0) + 1
    else: # query
    target = prefix val
    ans.append(prefix_count.get(target, 0))

    return ans

    def main():
    ops_str = sys.stdin.readline().strip()
    value_str = sys.stdin.readline().strip()

    ops = ops_str.split(",")
    value = list(map(int, value_str.split(",")))

    ans = handle(ops, value)

    print(",".join(map(str, ans)))

    if __name__ == "__main__":
    main()

    JavaScript

    const readline = require("readline");

    const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
    });

    const lines = [];

    rl.on("line", (line) => {
    lines.push(line.trim());
    });

    rl.on("close", () => {
    const ops = lines[0].split(",");
    const value = lines[1].split(",").map(Number);
    // 当前前缀和
    let prefix = 0;
    // 记录前缀和出现次数
    const prefixCount = new Map();
    const ans = [];

    for (let i = 0; i < ops.length; i++) {
    const val = value[i];

    if (ops[i] === "add") {
    prefix += val;
    prefixCount.set(prefix, (prefixCount.get(prefix) || 0) + 1);
    } else {
    const target = prefix val;
    ans.push(prefixCount.get(target) || 0);
    }
    }

    console.log(ans.join(","));
    });

    Go

    package main

    import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
    )

    func handle(ops []string, value []int) []int {
    // 当前前缀和
    prefix := int64(0)
    // 指定前缀和出现数量
    prefixCount := make(map[int64]int)
    ans := []int{}

    for i := 0; i < len(ops); i++ {
    val := value[i]

    if ops[i] == "add" {
    prefix += int64(val)
    prefixCount[prefix]++
    } else {
    target := prefix int64(val)
    ans = append(ans, prefixCount[target])
    }
    }

    return ans
    }

    func main() {
    reader := bufio.NewReader(os.Stdin)

    opsStr, _ := reader.ReadString('\\n')
    valueStr, _ := reader.ReadString('\\n')

    opsStr = strings.TrimSpace(opsStr)
    valueStr = strings.TrimSpace(valueStr)

    ops := strings.Split(opsStr, ",")
    valueParts := strings.Split(valueStr, ",")

    value := make([]int, len(valueParts))
    for i := range valueParts {
    v, _ := strconv.Atoi(valueParts[i])
    value[i] = v
    }

    ans := handle(ops, value)

    for i := range ans {
    if i > 0 {
    fmt.Print(",")
    }
    fmt.Print(ans[i])
    }
    }

    C语言

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    #define OFFSET 1000000000
    #define SIZE 2000000001 // 理论值域 [-1e9, 1e9]

    static int *cnt;

    int main() {
    char opsStr[1000000], valueStr[1000000];

    fgets(opsStr, sizeof(opsStr), stdin);
    fgets(valueStr, sizeof(valueStr), stdin);

    opsStr[strcspn(opsStr, "\\n")] = 0;
    valueStr[strcspn(valueStr, "\\n")] = 0;

    cnt = (int*)calloc(SIZE, sizeof(int));

    char *ops[100000];
    int value[100000];
    int n = 0;

    // 解析 ops
    char *token = strtok(opsStr, ",");
    while (token) {
    ops[n++] = token;
    token = strtok(NULL, ",");
    }

    int m = 0;
    token = strtok(valueStr, ",");
    while (token) {
    value[m++] = atoi(token);
    token = strtok(NULL, ",");
    }

    long prefix = 0;

    int first = 1;

    for (int i = 0; i < n; i++) {
    if (strcmp(ops[i], "add") == 0) {
    prefix += value[i];

    int idx = (int)(prefix + OFFSET);
    cnt[idx]++;

    } else {
    long target = prefix value[i];
    int idx = (int)(target + OFFSET);

    int res = cnt[idx];

    if (!first) printf(",");
    printf("%d", res);
    first = 0;
    }
    }

    free(cnt);
    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » 华为OD机试真题 新系统【统计盈利目标区间】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址