本周总结(7.6-7.12)(基础算法)


本周复习的知识点有:排序、二分、高精度、前缀和与差分、双指针算法、位运算、离散化、区间合并。

算法总结

快速排序

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

时间复杂度:O(nlogn)

归并排序

void msort(int a[], int l, int r)
{
    if (l >= r) return;
    int mid = l + r >> 1;
    msort(a, l, mid);
    msort(a, mid + 1, r);
    int i = l, j = mid + 1;
    int b[N], k = 0;
    while (i <= mid && j <= r)
    {
        if (a[i] < a[j]) b[k ++ ] = a[i ++ ];
        else b[k ++ ] = a[j ++ ];
    }
    while (i <= mid) b[k ++ ] = a[i ++ ];
    while (j <= r) b[k ++ ] = a[j ++ ];
    k = 0;
    for (int i = l; i <= r; i ++ ) a[i] = b[k ++ ];
}

时间复杂度:O(nlogn)

位运算

求数n的二进制第k位数字:n >> (k – 1) & 1
返回数n的最后一位1:lowbit(n) = n & -n

双指针算法

for (int i = 0, j = 0; i < n; i ++ )
{
	while (j < i && check(i, j)) j ++ ;
	//具体逻辑
}

时间复杂度:O(n)

二分

模板1

int bsearch1(int l, int r)
{
	while (l < r)
	{
		int mid = (l + r)/ 2;
		if (check(mid)) r = mid;
		else l = mid + 1;
	}
	return l;
}

模板2

int bsearch2(int l, int r)
{
	while (l < r)
	{
		int mid = (l + r + 1) / 2;
		if (check(mid)) l = mid;
		else r = mid - 1;
	}
	return l;
}

时间复杂度:O(logn) * check的时间复杂度

高精度

加法

string add(string a, string b)
{
    string c = "";
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    
    int t = 0; //进位
    int n = max(a.size(), b.size());
    for (int i = 0; i < n; i ++ )
    {
        if (i < a.size()) t += a[i] - '0';
        if (i < b.size()) t += b[i] - '0';
        c += '0' + t % 10;
        t /= 10;
    }
    if (t) c += '0' + t % 10;
    
    reverse(c.begin(), c.end());
    return c;
}

减法

bool check(string a, string b) //判断大小
{
    if (a.size() != b.size()) return a.size() < b.size();
    return a < b;
}

string sub(string a, string b)
{
    bool f = false;
    if (check(a, b))
    {
        swap(a, b);
        f = true;
    }
    
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    
    string c;
    int t = 0; //退位
    for (int i = 0; i < a.size(); i ++ )
    {
        t += a[i] - '0';
        if (i < b.size()) t -= b[i] - '0';
        if (t < 0)
        {
            c += '0' + t + 10;
            t = -1;
        }
        else
        {
            c += '0' + t;
            t = 0;
        }
    }
    
    reverse(c.begin(), c.end());
    int i = 0;
    while (c[i] == '0' && i + 1 < c.size()) i ++ ; //去除前导零
    c = c.substr(i, c.size() - i);
    if (c.size() == 0) c = '0';
    if (f) c = '-' + c;
    return c;
}

乘法

大数 × int型

string mul(string a, int b)
{
    string c;
    reverse(a.begin(), a.end());
    
    int t = 0;
    for (int i = 0; i < a.size(); i ++ )
    {
        t += (a[i] - '0') * b;
        c += t % 10 + '0';
        t /= 10;
    }
    
    while (t)
    {
        c += t % 10 + '0';
        t /= 10;
    }
    
    reverse(c.begin(), c.end());
    int i = 0;
    while (c[i] == '0' && i + 1 < c.size()) i ++ ;
    c = c.substr(i, c.size() - i);
    return c;
}

除法

大数 ÷ int型

string div(string a, int b, int &d) //d为余数
{
    string c;
    
    for (int i = 0; i < a.size(); i ++ )
    {
        d = d * 10 + a[i] - '0';
        c += d / b + '0';
        d = d % b;
    }
    
    int i = 0;
    while (i + 1 < c.size() && c[i] == '0') i ++ ;
    c = c.substr(i, c.size() - i);
    
    return c;
}

大数 ÷ 大数 可以用高精度减法实现,每次减去除数即可

其它总结

  1. sscanf、sprintf函数可用于字符串和数字间的互换

sscanf用法

int sscanf( const char *buffer, const char *format, ... );

返回值为成功赋值的个数,其它用法和scanf相同,string类型需要用c_str()转换
sprintf用法

int sprintf(char *string, char *format [,argument,...]);
  1. long long格式化输出时,Linux环境下为"lld" Windows环境下为"l64d"

  2. 1 << k 表示2的k次方

  3. 二维vector<vector<int>> a 行数:a.size() 列数:a[0].size()

  4. INT_MAX是int型的最大值,判断是a * 10是否超限,用a > INT_MAX / 10 INT_MAX=2^31-1

  5. int型负数转换为unsigned int时,相当于第32数位变为1

  6. 位运算是补码进行运算

  7. 二分查找函数(基于已排序的序列)
    lower_bound (beg,end,val)
    返回一个迭代器,指向非递减序列[first, last)中的第一个大于等于(>=)val的位置
    upper_bound (beg,end,val)
    返回一个迭代器,指向非递减序列[first, last)中的第一个大于 (>) val的位置

  8. 具有二分性不一定是对排序的序列,也可能是满足某条件

本周训练拓展题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值