AcWing 787. 归并排序 和 acwing 789. 数的范围

AcWing 787. 归并排序

一,知识概况:

1.并归思维。

 二,代码示例:

#include <iostream>

using namespace std;

const int N = 1e5 + 10;

int a[N], tmp[N];

void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int mid = l + r >> 1;

    merge_sort(q, l, mid), merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];
    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);

    merge_sort(a, 0, n - 1);

    for (int i = 0; i < n; i ++ ) printf("%d ", a[i]);

    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/39790/
来源:AcWing

 三,理解思路:

 一,并归思维:

想要并和归,自然要先分,把一个问题分成两个小分,依次分下去,但变成一个一个时,就可以开始判断且合并了(并),判断的结果返回回去和大一级的小分继续刚才的操作(归),直至输出结果。

使用条件:

1.可以进行分开判断,且判断条件简单。

2.判断数据需要总和,(归并思维是在于并,并的时候的判断大概率是来解决问题的。)

使用步骤:

1.定义中点。

2.进行分与并。(在归并排序中,分是把一串数据层层分组,到最后只有一个一个的数,无法对比进行返回,返回一组进行一次判断,返回上一层的数组判断,最终达到排序的效果。并则是里面的进行判断时进行的两组排序。)

3.找到都可以使用的判断条件。

临时模板:

int mid = l + r >> 1;

    merge_sort(q, l, mid), merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];
    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];

四,结语:

 要注意用计算机思维看问题,并归思维其实很简单,因为只看代码,没看见代码下面的计算很容易迷糊。

acwing 789. 数的范围

一,知识概括:

1.二分思维。

 二,代码示例:

#include <iostream>

using namespace std;

const int N = 100010;

int n, m;
int q[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    while (m -- )
    {
        int x;
        scanf("%d", &x);

        int l = 0, r = n - 1;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (q[mid] >= x) r = mid;
            else l = mid + 1;
        }

        if (q[l] != x) cout << "-1 -1" << endl;
        else
        {
            cout << l << ' ';

            int l = 0, r = n - 1;
            while (l < r)
            {
                int mid = l + r + 1 >> 1;
                if (q[mid] <= x) l = mid;
                else r = mid - 1;
            }

            cout << l << endl;
        }
    }

    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/39787/
来源:AcWing

三,思维理解: 

 一,二分思维:

yxc在说过二分的本质是边界,是通过判断mid与需要判断的值的关系,改变左右边界,要到达不断收缩区间进行判断,找到目标值。(比如数字4,可以确定精度。)

 使用则要注意题目:

1.可以通过一简单的判断找到目标值。

2.整个数据是具体的数据,可以进行缩减的。

3.目标值是可以确认的。

使用步骤:

1.确定mid值,

2.找到缩小区间的判断条件。

3.找到确认目标值的判断条件。

yxc的模板:

        while (l < r)
        {
             int mid = l + r + 1 >> 1;
             if (q[mid] <= x) l = mid;
             else r = mid - 1;
        }/* - 1就要 + 1。(注意:不加1,在只有一个数时,
                                mid会跑出范围,得到两个数据进行判断,则循环无法结束。)*/

        while (l < r)
        {
            int mid = l + r >> 1;
            if (q[mid] >= x) r = mid;
            else l = mid + 1;
        }//无需+ 1。

        while (r - l > 1e-8)//精度需求。
        {
            double mid = (l + r) / 2;
            if (mid * mid * mid >= x) r = mid;//本题是求根号3。
            else l = mid;
        }

四,结语:

 多练。

————这是鄙人没有什么学识,如有错误,请尽情留言。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lshyzz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值