第K小数 uva 10041 - Vito's Family poj 2388 Who's in the Middle

     题目链接

      很容易理解题目的意思,就是求某个点到其他点的距离之和,而且要让这个和最小,很明显是求中位数了。

     关于求中位数,一般的方法是我们先将整个数组进行排序,然后直接取出中位数,采用不同的排序方法可能有不同的时间复杂度,一般我们使用快排,时间复杂度为O(nlogn),有没有更快的方法? 答案是肯定的。

    这里有一种时间复杂度为O(n)的算法,下面是此题的解题代码。


//uva 10041 - Vito's Family
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;

int a[40000];

int partition(int l, int r)
{
    int x = a[r];
    int i = l-1;
    for (int j = l; j < r; j++)
    {
        if (x >= a[j])
        {
            i++;
            swap(a[i], a[j]);
        }
    }
    ++i;
    swap(a[i],a[r]);
    return i;
}

int select(int l, int r, int k)
{
    if (l >= r)
        return a[l];
    int p = partition(l, r);
    if (k == p)
        return a[k];
    else if(k > p)
        return select(p + 1, r, k);
    else
        return select(l, p - 1, k);
}

int main()
{
    int t, n;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        for (int i = 0; i < n; i++)
            scanf("%d",&a[i]);
        int x = select(0, n-1, n/2);
        int s = 0;
        for (int i = 0; i < n; i++)
        {
            s += abs(a[i] - x);
        }
        printf("%d\n",s);
    }
    return 0;
}

       了解快排的人对int (int l, int r) 这个函数很熟悉,因为这是在快排中用到的,它的作用是对数组的某一段选一个分界点,使得该点左边的数都不大于该点的数,右边的点不小于该点的数,也就是说我们通过一次调用这个函数确定一个数的位置,快排是将该点两边分别进行递归操作,时间复杂度为O(nlogn),而select只是对一边进行递归操作(有点像二分的递归形式),所以时间复杂度仅为O(nlogn)。

        其实还有时间复杂度更低的算法,划分树。。。   时间复杂度为log(n) 。。。。。   划分树的优点是可以对某个区间进行多次的查询,并不改变原序。


poj 2388

//poj 2388
#include <stdio.h>
#include <algorithm>
using namespace std;

const int maxn = 10005;

int a[maxn];

int partition(int l, int r)
{
    int x = a[r];
    int ol = l;
    for (int i = l; i < r; i++)
    {
        if (a[i] < x)
        {
            swap(a[ol], a[i]);
            ol++;
        }
    }
    swap(a[r], a[ol]);
    return ol;
}

int search(int l, int r, int k)
{
    int pos = partition(l, r);
    if (l == r)
        return a[l];
    if (k == pos)
        return a[k];
    else if (pos < k)
        return search(pos+1, r, k);
    else if (pos > k)
        return search(l, pos-1, k);
}

int main()
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        for (int i = 0; i < n; i++)
            scanf("%d",&a[i]);
        printf("%d\n",search(0, n-1, n/2));
    }
    return 0;
}


     

转载于:https://www.cnblogs.com/xindoo/archive/2013/04/03/3595164.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lotka-Volterra竞争模型是一种描述两个或多个物种相互竞争关系的数学模型。该模型由阿尔弗雷德&middot;J&middot;罗特卡(Alfred J. Lotka)和维托里奥&middot;沃尔泰拉(Vito Volterra)提出,并广泛应用于生态学领域。 在Lotka-Volterra竞争模型中,假设有两个物种A和B,它们在资源有限的环境中相互竞争。模型基于以下几个假设: 1. 环境资源有限:资源供应有限,无法满足两个物种的需求。 2. 竞争强度恒定:物种A和B之间的竞争强度是恒定的,不随时间变化。 3. 繁殖率与资源利用成正比:物种的繁殖率与其对资源的利用成正比,即利用资源越多,繁殖率越高。 基于以上假设,Lotka-Volterra竞争模型可以用以下方程来描述两个物种数量的变化: dN_a/dt = r_a * N_a * (1 - (N_a + alpha * N_b) / K_a) dN_b/dt = r_b * N_b * (1 - (N_b + beta * N_a) / K_b) 其中, - dN_a/dt和dN_b/dt表示物种A和物种B的数量变化率; - r_a和r_b表示物种A和物种B的无竞争增长率; - N_a和N_b表示物种A和物种B的数量; - alpha和beta表示物种A和物种B对彼此的竞争强度; - K_a和K_b表示物种A和物种B的环境容量,即资源供应的上限。 这些方程描述了物种数量随时间的变化,考虑了两个物种之间的竞争关系和资源的限制。通过数值模拟或解析求解这些方程,可以研究物种之间的竞争结果、平衡稳定性以及竞争强度对物种数量的影响。 需要注意的是,Lotka-Volterra竞争模型是一个简化的模型,忽略了许多现实环境中的复杂因素。在实际应用中,需要根据具体情况进行模型参数的估计和调整,以更好地描述实际生态系统中的竞争关系。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值