青训营X豆包MarsCode 技术训练营,第260题

62 阅读4分钟

答题实践笔记

题目解析

题目描述

小F手中有一串数字,他希望这些数字能按照一定的规则两两配对。配对的规则如下:

  • 数字对中的两个数字的差的绝对值必须大于等于给定的差异值M。
  • 每个数字只能被配对一次,不能出现在其他的数字对中。
  • 小F想知道给定的数字中,最多能成功配对出多少对数字。

示例

  • 输入:N = 4, M = 2, X = [1, 3, 3, 7]
  • 输出:2

思路分析

要在数组中找到最多的数字对,使得每对数字的差的绝对值大于等于M,且每个数字只能使用一次。为了实现这个目标,我们需要:

  1. 排序数组:将数组从小到大排序,方便比较数字之间的差值。

  2. 双指针技巧:使用两个指针leftright,分别指向数组的不同部分,以便快速找到符合条件的数字对。

  3. 贪心策略:尽可能地匹配最小的数字对,以保证后续还有更多的数字可以配对。

图解说明

假设排序后的数组为[1, 3, 3, 7],差异值M = 2

索引:   0   1   2   3
值:    [1,  3,  3,  7]
  • 初始化left = 0(指向1),right = 2(指向第二个3)。
  • 比较X[right] - X[left] = 3 - 1 = 2 >= M,可以配对,count++left++right++
  • 现在left = 1(指向第一个3),right = 3(指向7)。
  • 比较X[right] - X[left] = 7 - 3 = 4 >= M,可以配对,count++left++right++
  • 指针越界,结束循环。

代码详解

#include <iostream>
#include <vector>
#include <algorithm>

int solution(int N, int M, std::vector<int> X) {
    // 将数组排序
    std::sort(X.begin(), X.end());

    // 初始化指针和计数器
    int left = 0;
    int right = N / 2;
    int count = 0;

    // 使用双指针遍历数组
    while (left < N / 2 && right < N) {
        if (X[right] - X[left] >= M) {
            // 找到符合条件的配对
            count++;
            left++;
            right++;
        } else {
            // 不符合条件,移动右指针寻找下一个可能的数字
            right++;
        }
    }

    return count;
}

int main() {
    std::vector<int> arr1 = {1, 3, 3, 7};
    std::cout << solution(4, 2, arr1) << std::endl; // 输出:2

    return 0;
}

代码解释

  • 排序:为了方便比较,首先对数组进行排序。
  • 初始化left从数组起始位置开始,right从数组中间位置开始。
  • 循环条件left小于N / 2right小于N,确保指针不越界。
  • 判断配对
    • 如果X[right] - X[left] >= M,则找到一对符合条件的数字,计数器加一,leftright同时移动到下一个位置。
    • 如果不满足条件,right右移,继续寻找。

知识总结

1. 贪心算法

贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。

  • 应用场景:求解最优化问题,如最大化或最小化某种资源的使用。
  • 特点:不回溯,不考虑所有可能的情况,只关注当前最优解。

2. 双指针技巧

双指针是一种常用的数组遍历方法,通常用于有序数组,可以高效地解决一类问题。

  • 前提条件:数组有序或部分有序。
  • 用途:查找满足特定条件的元素对或子数组。

学习建议

  • 理解排序的重要性:排序往往是解决数组问题的第一步,可以降低问题的复杂度。
  • 熟练掌握双指针:多练习使用双指针解决问题,如两数之和、三数之和等经典问题,这些在掘金里面被包装了一个背景,如果想直接找原题可以去leetcode。
  • 练习贪心算法:理解贪心算法的思想,在实践中体会其应用场景和局限性。

学习计划

1. 制定刷题计划

  • 每日一题:不用说坚持每天至少解决一道算法题,但是还是要坚持,不能停很久,要逐步提升算法思维。
  • 分类练习:按主题(如贪心、双指针、动态规划等)进行专项练习,深入理解各类算法思想,可以看看代码随想录。

2. 利用错题进行针对性学习

  • 错题整理:将做错的题目记录下来,分析错误原因。
  • 定期复习:秋招或者找实习之前每周复习错题,巩固薄弱环节。
  • 反思总结:总结解题思路,寻找更优的解法。

工具运用

1. 结合AI助手

  • 寻求解题思路:在遇到困难时,可以借助豆包AI助手获取提示和思路,但不要直接依赖答案。
  • 代码审查:让AI帮助检查代码中的潜在错误,优化代码效率。
  • 主动思考:在求助AI或他人之前,先自己尝试解决问题,培养独立思考能力。
  • 合理使用工具:将AI和其他资源作为辅助工具,而非依赖,注重自身能力的提升。

#青训营笔记创作活动