牛客-【237题】算法基础精选题单-第二章 递归、分治

递归

NC15173 The Biggest Water Problem

简单递归,直接暴力

#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
#define de(x) cout << x << " ";
#define sf(x) scanf("%d", &x);
#define Pu puts("");
#define ll long long
int n, m, ans;
int fun(int x) {
    if (x / 10 == 0) {
        return x;
    }
    int res = 0;
    while (x) {
        res += (x % 10);
        x /= 10;
    }
    return fun(res);
}
int main() {
    cin >> n;
    cout << fun(n) << endl;
    return 0;
}

NC22164 更相减损术

注意处理的时候,使用较大的值去减去较小的值

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define sf(x) scanf("%d", &x);
#define de(x) cout << x << " ";
#define Pu puts("");
const int N = 1e5 + 9, mod = 1e9 + 7;
int n, m, ans;
int fun(int x, int y) {
    if (x % y == 0) {
        return y;
    }
    int t = x - y;
    if (t > y) {  // 大数放前面
        return fun(t, y);
    } else {
        return fun(y, t);
    }
}
int main() {
    cin >> n >> m;
    cout << fun(max(n, m), min(n, m)) << endl;
    return 0;
}

NC208813 求逆序数

做法一:直接暴力求解

#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 2e3 + 10;
#define de(x) cout << x << " ";
#define sf(x) scanf("%d", &x);
#define Pu puts("");
#define ll long long
int n, m, ans;
int a[N];
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        sf(a[i])
    }
    ans = 0;
    // 做法一:直接暴力求解
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            if (a[j] < a[i])
                ans++;
        }
    }
    de(ans);
    return 0;
}

做法二:归并排序,在归并的过程中记录逆序对

#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 2e3 + 10;
#define de(x) cout << x << " ";
#define sf(x) scanf("%d", &x);
#define Pu puts("");
#define ll long long
int n, m, ans;
int a[N], b[N];
void mesort(int l, int r) {
    // de(l) de(r) de(ans) Pu;
    if (l == r)
        return;
    int mid = l + r >> 1;
    mesort(l, mid);
    mesort(mid + 1, r);
    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r) {
        if (a[i] <= a[j])
            b[++k] = a[i++];
        else {  // 从i-mid的数值一定都比j上的数值大
            b[++k] = a[j++];
            ans += mid - i + 1;
            // de(l) de(r) de(mid) de(i) de(999) Pu;
        }
        // 会不会重复统计?
        // 不会,因为归并排序我们是看左右两部分,而这两部分的长度是不断增加的
        // 各个l-r区间相互独立
    }
    while (i <= mid)
        b[++k] = a[i], i++;
    while (j <= r)
        b[++k] = a[j], j++;
    for (int o = l, k = 0; o <= r; o++) {
        a[o] = b[++k];
    }
    // de(l) de(r) de(ans) Pu;
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        sf(a[i])
    }
    ans = 0;
    // 做法二:归并排序,在归并的过程中记录逆序对
    mesort(1, n);
    de(ans);
    return 0;
}

NC207028 第k小数

使用快排

#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 5e6 + 10;
#define de(x) cout << x << " ";
#define sf(x) scanf("%d", &x);
#define Pu puts("");
#define ll long long
int n, m, ans;
int a[N];
int k;
inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

int find_qsort(int l, int r) {
    if (l == r)
        return a[l];
    int mid = a[l + r >> 1];
    int i = l, j = r;
    while (i <= j) {
        while (a[j] > mid)
            j--;
        while (a[i] < mid)
            i++;
        if (i <= j) {
            swap(a[i], a[j]);
            i++;
            j--;
        }
    }
    if (k <= j)
        find_qsort(l, j);
    else if (k >= i)
        find_qsort(i, r);
    return a[k];
}
int main() {
    int T;
    cin >> T;
    while (T--) {
        cin >> n >> k;
        for (int i = 1; i <= n; i++) {
            a[i] = read();
        }
        cout << find_qsort(1, n) << endl;
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值