青训营刷题1 | 豆包MarsCode AI刷题

37 阅读4分钟

小S的倒排索引

题目描述

小S正在帮助她的朋友们建立一个搜索引擎。为了让用户能够更快地找到他们感兴趣的帖子,小S决定使用倒排索引。倒排索引的工作原理是:每个单词都会关联一个帖子ID的列表,这些帖子包含该单词,且ID按从小到大的顺序排列。
例如,单词“夏天”可能出现在帖子1、帖子3和帖子7中,那么这个单词的倒排链就是 [1, 3, 7]。如果用户想同时找到包含“夏天”和“海滩”的帖子,小S需要找出两个倒排链的交集,且将结果按照从大到小的顺序输出。现在,给定两个单词的倒排链数组 a 和 b,请你帮助小S找出同时包含这两个单词的帖子ID,并按从大到小的顺序返回结果。

测试样例

样例1:

输入:a = [1, 2, 3, 7], b = [2, 5, 7]
输出:[7, 2]

样例2:

输入:a = [1, 4, 8, 10], b = [2, 4, 8, 10]
输出:[10, 8, 4]

思路分析

核心思想:双指针

为了找到两个倒排链的交集并按从大到小的顺序输出结果,我们可以使用双指针

  1. 初始化两个指针,分别指向两个倒排链的末尾。

  2. 比较两个指针所指的元素,如果相等,则将该元素加入结果列表,并同时向前移动两个指针;如果不相等,则移动指向较小元素的指针。

  3. 重复步骤2,直到其中一个指针超出链表范围。

  4. 反转结果列表,以获得从大到小的顺序。

完整代码

#include <iostream>
#include <vector>
using namespace std;

vector<int> solution(vector<int>& a, vector<int>& b) {
    // write code here
     vector<int> result;
    int i = a.size() - 1;
    int j = b.size() - 1;

    while (i >= 0 && j >= 0) {
        if (a[i] == b[j]) {
            result.push_back(a[i]);
            i--;
            j--;
        //a的数字更大,i--
        } else if (a[i] > b[j]) {
            i--;
        } else {
        //b的数字更大,j--
            j--;
        }
    }
    return result;
}

int main() {
    vector<int> a1 = {1, 2, 3, 7};
    vector<int> b1 = {2, 5, 7};
    vector<int> res1 = solution(a1, b1);
    cout << (res1 == vector<int>{7, 2}) << endl;

    vector<int> a2 = {1, 4, 8, 10};
    vector<int> b2 = {2, 4, 8, 10};
    vector<int> res2 = solution(a2, b2);
    cout << (res2 == vector<int>{10, 8, 4}) << endl;

    vector<int> a3 = {3, 5, 9};
    vector<int> b3 = {1, 4, 6};
    vector<int> res3 = solution(a3, b3);
    cout << (res3 == vector<int>{}) << endl;

    vector<int> a4 = {1, 2, 3};
    vector<int> b4 = {1, 2, 3};
    vector<int> res4 = solution(a4, b4);
    cout << (res4 == vector<int>{3, 2, 1}) << endl;

    return 0;
}

小E的射击训练

题目描述

小E正在训练场进行射击练习,靶有10个环,靶心位于坐标(0, 0)。每个环对应不同的得分,靶心内(半径为1)得10分,依次向外的每个环分数减少1分。若射击点在某个半径为i的圆内,则得11-i分。如果射击点超出所有的环,则得0分。

根据给定的射击坐标(x, y),请计算小E的射击得分。

测试样例

样例1:

输入:x = 1, y = 0
输出:10

样例2:

输入:x = 1, y = 1
输出:9

思路分析

为了计算小E的射击得分,我们需要确定射击点(x, y)到靶心(0, 0)的距离,然后根据这个距离来判断其在哪个环内,从而确定得分。

  1. 计算距离:使用欧几里得距离公式计算点(x, y)到靶心(0, 0)的距离。公式为:

    distance=x2+y2distance=x2+y2​

  2. 判断环数:靶心内(半径为1)得10分,依次向外的每个环分数减少1分。半径为i的圆内得分为11-i分。

    • 如果距离小于等于1,得分是10分。
    • 如果距离大于1且小于等于2,得分是9分。
    • 依此类推,直到距离大于10,得分是0分。

完整代码

#include <iostream>
#include <cmath>

// 计算距离的函数
double calculateDistance(double x, double y) {
    return std::sqrt(x * x + y * y);
}

int solution(int x, int y) {
    double distance = calculateDistance(x, y);
    if (distance <= 1.0) {
        return 10;  // 在半径为1的圆内
    } else if (distance <= 2.0) {
        return 9;   // 在半径为2的圆内
    } else if (distance <= 3.0) {
        return 8;   // 在半径为3的圆内
    } else if (distance <= 4.0) {
        return 7;   // 在半径为4的圆内
    } else if (distance <= 5.0) {
        return 6;   // 在半径为5的圆内
    } else if (distance <= 6.0) {
        return 5;   // 在半径为6的圆内
    } else if (distance <= 7.0) {
        return 4;   // 在半径为7的圆内
    } else if (distance <= 8.0) {
        return 3;   // 在半径为8的圆内
    } else if (distance <= 9.0) {
        return 2;   // 在半径为9的圆内
    } else if (distance <= 10.0) {
        return 1;   // 在半径为10的圆内
    } else {
        return 0;   // 超出所有环
    }
    return 0;
}

int main() {
    //cout << (solution(1, 0) == 10) << endl;
    //cout << (solution(1, 1) == 9) << endl;
    //cout << (solution(0, 5) == 6) << endl;
    //cout << (solution(3, 4) == 6) << endl;
    return 0;
}

本篇完!