C/C++个人学习博客

12月主要学习了c++中stl相关知识
空余时间学习了些基础算法

STL

1.容器

string容器

第一次学到这玩意感觉强的一比啊,做一些字符串的题感觉比c的char方便了不少。
在这里插入图片描述
这是学长课堂算法方向第六次课中的第一题,用string做的(主要是string类进行字符串比较直接== 就行了不用strcmp)。
除了直接使用==,!=等关系运算符进行string类字符串的比较,还可以用+=来进行字符串的拼接。

string s="ab";
s+='c';

这样s将由"ab"变为"abc"。
在这里插入图片描述
当时的第二道题。(虽然这道题只过了63%的测试用例 )代码中用到了string类的两个函数,一个是.size(),作用与c的strlen()相似,但是使用方法不同
代码中还用到了string& assign(const string &s, int start, int n);意思是将s从start开始n个字符赋值给字符串.
使用string类读入一行字符串(包括空格),遇回车结束

int n;
string s;
cin >> n;
getchar(); //cin.get()
getline(cin, s);//可正确读入下一行的输入

Vector容器

vector为可变长数组(动态数组),定义的vector数组可以随时添加数值和删除元素。
头文件#include <vector>
使用vector定义一个数组与平常c语言中定义数组的方式不一样

vector<int> a; //定义一个名为a的一维数组,数组存储int类型数据
vector<double> b;//定义一个名为b的一维数组,数组存储double类型数据
vector<int> a{1, 2, 3, 4, 5};
vector<int> v[5];//定义二维vector数组
vector<vector<int>> v;//定义一个行和列均可变的二维数组

在vector容器中常用的一些函数

c.front();//返回第一个数据
c.back();//返回数组中的最后一个数据
c.push_back();//在尾部加一个数据
c.size();//返回实际数据个数
c.clear();//清楚所有元素
c.begin();//返回首元素的迭代器
c.end();//返回最后一个元素**后一个位置**的迭代器
c.insert(it, x);//向任意迭代器it插入一个元素x
例:c.insert(c.begin() + 2,-1);//将-1插入c[2]的位置

用迭代器访问vector数组

vector<int> vi;
vector<int>::iterator it = vi.begin();//迭代器it指向vi第一个元素(可以auto it=vi.begin())
for(; it != vi.end();it ++)
	cout << *it << " ";//遍历vi中所有元素

智能指针遍历vector数组

vector<int> a(n);
for (auto &x: a) {
    cin >> x; // 进行输入
for(auto val : v) {
	cout << val << " "; // 进行输出

其他的容器如queue,map等还没具体使用做过题,暂且不写。

函数

sort排序

时间复杂度是:O(NlogN),说是快速排序和归并排序的结合体。

int a[N]; //
sort(a , a + n); 对 a 数组的[0, n]位置进行从小到大排序
sort(a, a + n, greater<int>());//从大到小

vector<int> b(n + 1); // vector数组定义
sort(b.begin() + 1, b.end());
sort(b.begin() + 1, b.end(), greater<int>()); // 降序

reverse

将序列翻转

string s = "abcde";
reverse(s.begin(), s.end());//对s进行翻转
cout << s << '\n';//edcba

int a[] = {1, 2, 3, 4};
reverse(a, a + 4);//对a数组进行翻转
cout << a[0] << a[1] << a[2] << a[3];//4321

算法学习

在看acwing基础算法课
目前只学了快排,归并排序,高精度加减乘除,二分,前缀和,差分,双指针,位运算 (有点没懂)主要讲讲二分。

整数二分算法模板
bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

这是二分常见两种模版,第一种没啥好说的,主要是第二种,由于c语言在做除法时是向下取整,在计算mid的时候要+1,不然可能会出现边界问题造成死循环。
在这里插入图片描述
洛谷上的一道二分题(提交了得有10多次才过,要不就全wa要不就全tle),开始我的思路是先将树的高度排序,以最矮的作为l最高的作为r进行二分,遍历每棵树的高度-mid,如果大于0就加入sum,当sumM的时候直接return 0,但是属于是没认真读题了,说是至少为M米,就是说测试数据不是刚好能summid的。后面一句提醒了如果再升高1米,将得不到M米木材,于是我就又定义了一个mid2=mid+1,当sum2和sum同时满足条件时候返回mid。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	long long n, m, i, tmp, sum = 0, sum2=0;
	cin >> n >> m;
	long long * s = new long long[n];
	for (i = 0; i < n; i++) cin >> s[i];
	sort(s, s + n);
	int l = s[0], r = s[n - 1], mid = (l + r) / 2,mid2=mid+1;
	while (l < r)
	{
		for (i = 0; i < n; i++)
		{
			if (s[i] - mid >= 0) sum += s[i] - mid;
			if (s[i] - mid2 >= 0) sum2 += s[i] - mid2;
		}
		if (sum >= m&&sum2<m)
		{
			cout << mid;
			return 0;
		}
		else
		{
			if (sum < m) r = mid;
			else l = mid + 1;
			mid = (l + r) / 2;
			mid2 = mid + 1;
			sum = 0;
			sum2 = 0;
		}

	}
	return 0;
}
  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值