算法训练总结(C++)

下面和大家分享一下最近算法学习的收获顺便帮助自己回顾一下(虽然这可能才是主要目的qaq),共勉!

最近新学会的算法思想:

1.递推预存(于数组)

2.随机选择(主要是随机快速排序降低时间复杂度)

新学会的代码语句:

1.在区间[left,right]生成随机数:

法一:只适用于生成范围不大于RAND_MAX的随机数:

rand()%(right-left +1) + left;

(其中rand()生成[0,RAND_MAX]范围的整数,当区间差比RAND_MAX小时,rand()%(right-left +1)生成[0,right-left]范围的整数,注意如果区间差比RAND_MAX大,rand()%(right-left +1)就只能生成[0,RAND_MAX]范围的整数)

法二:(Important,推荐使用) 适用于生成任意范围的随机数,也就是说范围可以大于RAND_MAX:

1.0 * rand()/RAND_MAX * (right - left) + left;

(解释:rand()生成[0,RAND_MAX]范围的整数,乘以1.0用于将计算由整型除法转化为浮点型除法,从而浮点型除以cstdlib库里的一个常量RAND_MAX就得到[0,1]范围的浮点数,再乘以区间长度,然后加上左端点值就得到[left,right]范围的随机数。)

使用上面rand()函数生成随机数需要在适当位置加入下面代码:

#include <cstdlib>

#include <ctime>

srand((unsigned)time(NULL)); //初始化随机数种子

快速排序易错点总结:

首先,快速排序的基本思路是:选择待排序数组中的一个数,由双指针法确定其排序后的最终位置,再递归快速排序该位置左、右两个待排序数组。(其中待排序数组用左端点下标和右端点下标即可表示,将原待排序数组置为全局变量数组就不需要传入函数作为参数即可使用)

经典快速排序算法如下代码:

int partition(int l,int r){
    int temp = a[l];//选取左端点值作为此轮要确定最终位置的数
    while(l < r){
        while(l<r && a[r]>temp){ //注意这里不要写成if,if就最多走一步了,while才会一直走直到你不让我走
            r--;
        }
        a[l] = a[r];
        while(l<r && a[l]<=temp){ //同上不要写成if,同时注意这里虽然外面大循环有l<r的条件,但是执行了r--或l++后始终需要满足l<r,因此这两处的条件中的“l<r &&”并不多余
            l++;
        }
        a[r] = a[l];
    }
    a[l] = temp;
    return l;
}

void quickSort(int l, int r){
    if(l < r){ //注意这里不要写成while了,不然就会进入死循环。下面递归就是自动循环了。
        int pos = partition(l,r);
        quickSort(l,pos-1);
        quickSort(pos+1,r);
    }
}

简言之:

快排基本思路:

只要待排数组元素个数大于1,就选择元素确定最终位置,再对该位置左右区间递归选择元素确定最终位置。

待保留思考的问题:

1.归并排序如何写?

2.如何用二分算法思想快速求双序列的中位数?

双序列中位数题目如下:

题解代码如下(But我没看懂~_~):

#include <cstdio>
#include <algorithm>
using namespace std;

const int MAXN = 100000;
int n, m, a[MAXN], b[MAXN];

int getMax(int a[], int i, int b[], int j) {
    if (i < 0) {
        return b[j];
    }
    if (j < 0) {
        return a[i];
    }
    return max(a[i], b[j]);
}

int getMin(int a[], int i, int b[], int j) {
    if (i >= n) {
        return b[j];
    }
    if (j >= m) {
        return a[i];
    }
    return min(a[i], b[j]);
}

double binarySearch(int n, int a[], int m, int b[]) {
    int leftPartCount = (n + m + 1) / 2;
    int l = 0, r = n;
    while (l < r) {
        int mid = (l + r + 1) / 2;
        int j = leftPartCount - mid;
        if (a[mid - 1] > b[j]) {
            r = mid - 1;
        } else {
            l = mid;
        }
    }
    if ((n + m) % 2) {
        return (double)getMax(a, l - 1, b, leftPartCount - l - 1);
    } else {
        return (getMax(a, l - 1, b, leftPartCount - l - 1) + getMin(a, l, b, leftPartCount - l)) / 2.0;
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    for (int i = 0; i < m; i++) {
        scanf("%d", &b[i]);
    }
    if (n < m) {
        printf("%.1f", binarySearch(n, a, m, b));
    } else {
        printf("%.1f", binarySearch(m, b, n, a));
    }
    return 0;
}

题目及题解来源(晴问算法

这两个问题先留着思考吧,等我有收获再和大家分享^>^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值