6 种思路搞定 GESP 一级真题:「交朋友」问题的全面解法

四季读书网 3 0
6 种思路搞定 GESP 一级真题:「交朋友」问题的全面解法

在 GESP 一级的经典题目「交朋友」中,我们需要帮 Alice 找到身高最接近的朋友,若有多人符合,则选择其中最矮的那位。这道题看似简单,却能衍生出多种不同的解题思路,非常适合用来锻炼编程逻辑。不过对于考一级的小朋友还是太难了。不过别抱怨,让我们勤学苦练到没有意外!

6 种思路搞定 GESP 一级真题:「交朋友」问题的全面解法 第1张
6 种思路搞定 GESP 一级真题:「交朋友」问题的全面解法 第2张

方法一:逐个比较法(最基础推荐)

核心思想

直接遍历所有小朋友,逐个计算与 Alice 的身高差,动态更新最优解。

  • 代码特点
    无数组、无复杂循环,仅用基础变量和if判断,代码最短、逻辑最直观。
  • 优势
  • 完全贴合 GESP 一级知识点,新手极易理解,几乎无 bug 风险。
  • 适用场景
    刚接触编程、只掌握变量与条件判断的初学者。
    #include <iostream>using namespace std;int main() {    int alice, h1, h2, h3;    cin >> alice >> h1 >> h2 >> h3;    int best = h1;    int min_diff = alice - h1;    if (min_diff < 0) min_diff = -min_diff;    int diff = alice - h2;    if (diff < 0) diff = -diff;    if (diff < min_diff || (diff == min_diff && h2 < best)) {        min_diff = diff; best = h2;    }    diff = alice - h3;    if (diff < 0) diff = -diff;    if (diff < min_diff || (diff == min_diff && h3 < best)) {        min_diff = diff; best = h3;    }    cout << best << endl;    return 0;}

    方法二:数组遍历法(代码复用优化)

    核心思想

  • 将小朋友身高存入数组,用循环遍历替代重复的比较代码,提升代码简洁性。

    #include <iostream>using namespace std;int main() {    int h[4];    cin >> h[0] >> h[1] >> h[2] >> h[3];    int best = h[1];    int min_diff = h[0] - h[1];    if (min_diff < 0) min_diff = -min_diff;    for (int i = 2; i < 4; i++) {        int diff = h[0] - h[i];        if (diff < 0diff = -diff;        if (diff < min_diff || (diff == min_diff && h[i] < best)) {            min_diff = diff; best = h[i];        }    }    cout << best << endl;    return 0;}

    方法三:排序位置判断法(直观生活逻辑)

    核心思想

  • 先将所有身高排序,找到 Alice 在序列中的位置,再通过比较左右邻居确定最优解。

    • 代码特点
      引入数组和单循环,避免重复书写相同逻辑,结构更清晰。
    • 优势
      适合理解数组与循环的配合,为后续学习打下基础。
    • 适用场景
      已掌握数组基础、希望简化重复代码的学习者。
#include <bits/stdc++.h>using namespace std;int main() {    int a[4];    cin >> a[0] >> a[1] >> a[2] >> a[3];    int alice = a[0];    // 冒泡排序    for (int i = 0; i < 3; i++) {        for (int j = 0; j < 3 - i; j++) {            if (a[j] > a[j+1]) swap(a[j], a[j+1]);        }    }    int pos = 0;    for (int i = 0; i < 4; i++) {        if (a[i] == alice) { pos = i; break; }    }    int friend_h;    if (pos == 0) friend_h = a[1];    else if (pos == 3) friend_h = a[2];    else {        int left_diff = alice - a[pos-1];        int right_diff = a[pos+1] - alice;        if (left_diff < right_diff) friend_h = a[pos-1];        else if (right_diff < left_diff) friend_h = a[pos+1];        else friend_h = a[pos-1];    }    cout << friend_h << endl;    return 0;}

方法四:差值 + 身高联合排序法(进阶排序思维)

核心思想
将「身高差」和「身高本身」绑定,通过一次排序同时满足 “差距最小” 和 “更矮” 的规则。
    • 代码特点
      需要手动实现冒泡排序,代码量稍多,但逻辑完全符合生活直觉。
    • 优势
      将抽象问题转化为 “找邻居” 的具象场景,便于理解边界情况。
    • 适用场景
      想锻炼排序能力、喜欢具象化思考的同学。
  • 将「身高差」和「身高本身」绑定,通过一次排序同时满足 “差距最小” 和 “更矮” 的规则。

    #include<bits/stdc++.h>using namespace std;intmain(){    int alice, h1, h2, h3;    cin >> alice >> h1 >> h2 >> h3;    int diff[3], height[3];    // 计算差值    diff[0] = abs(alice - h1); height[0] = h1;    diff[1] = abs(alice - h2); height[1] = h2;    diff[2] = abs(alice - h3); height[2] = h3;    // 联合排序    for (int i = 0; i < 2; i++) {        for (int j = 0; j < 2 - i; j++) {            if (diff[j] > diff[j+1]) {                swap(diff[j], diff[j+1]);                swap(height[j], height[j+1]);            } else if (diff[j] == diff[j+1] && height[j] > height[j+1]) {                swap(height[j], height[j+1]);            }        }    }    cout << height[0] << endl;    return 0;}

    方法五:枚举法(穷举所有情况)

    核心思想

  • 由于只有 3 个小朋友,直接穷举所有可能的比较情况,用if-else完成判断。
    • 代码特点
      用两个数组分别存储差值和身高,排序时先比差值、再比身高。
    • 优势
      思路新颖,能锻炼多关键字排序的思维,扩展性强。
    • 适用场景
      希望进阶、探索排序灵活应用的学习者。
  • 由于只有 3 个小朋友,直接穷举所有可能的比较情况,用if-else完成判断。

    #include<bits/stdc++.h>using namespace std;intmain(){    int alice, h1, h2, h3;    cin >> alice >> h1 >> h2 >> h3;    int d1 = abs(alice - h1);    int d2 = abs(alice - h2);    int d3 = abs(alice - h3);    int best;    if (d1 < d2 && d1 < d3) best = h1;    else if (d2 < d1 && d2 < d3) best = h2;    else if (d3 < d1 && d3 < d2) best = h3;    else if (d1 == d2 && d1 < d3) best = (h1 < h2) ? h1 : h2;    else if (d1 == d3 && d1 < d2) best = (h1 < h3) ? h1 : h3;    else if (d2 == d3 && d2 < d1) best = (h2 < h3) ? h2 : h3;    else best = min({h1, h2, h3});    cout << best << endl;    return 0;}
    方法六:向外扩散枚举法(巧妙暴力思路)
  • 核心思想
    从 Alice 的身高开始,先往矮的方向(减 1)、再往高的方向(加 1)一步步扩散,找到第一个存在的身高。
    • 代码特点
      无循环、无数组,完全用条件判断覆盖所有场景,逻辑直白。
    • 优势
      极端适合初学者理解 “所有可能性” 的思维,代码无任何隐藏逻辑。
    • 适用场景
      刚学if-else、想彻底理清所有边界条件的新手。
  • 核心思想

  • 从 Alice 的身高开始,先往矮的方向(减 1)、再往高的方向(加 1)一步步扩散,找到第一个存在的身高。

    • 代码特点
      用死循环 +break实现,代码极简,自动满足 “更矮优先” 的规则。
    • 优势
      思路极具创造性,完全贴合题目整数身高的特性,是 GESP 一级的 “高分巧解” 代表。
    • 适用场景
      喜欢探索巧思、想提升编程趣味性的同学。
    #include <iostream>using namespace std;int main() {    int h, h1, h2, h3;    cin >> h >> h1 >> h2 >> h3;    for (int i = 0;; i++) {        if (h-i == h1 || h-i == h2 || h-i == h3) {            cout << h-ibreak;        }        if (h+i == h1 || h+i == h2 || h+i == h3) {            cout << h+i; break;        }    }    return 0;}

写在最后

    • 这道「交朋友」的题目,看似简单,却能衍生出 6 种截然不同的思路,这正是编程的魅力所在 ——没有唯一正确的解法,只有更适合当前场景的思路

      对于 GESP 一级备考的同学,我最推荐先掌握「逐个比较法」和「枚举法」,这两种方法最稳妥、最不容易出错;学有余力的同学可以尝试「向外扩散法」,感受编程巧思带来的乐趣。

抱歉,评论功能暂时关闭!