【算法刷题】基础用法

综述:
💞目的:本系列是个人整理为了秋招算法的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
🥰来源:材料主要源于网上知识点进行的,每个代码参考热门博客和GPT3.5,其中也可能含有一些的个人思考。
🤭结语:如果有帮到你的地方,就点个赞关注一下呗,谢谢🎈🎄🌷!!!
🌈数据结构基础知识总结篇



😊点此到文末惊喜↩︎


ACM模式

  1. 基础输入要点
    • 引用库需要自己加上对应的库,如#include <algorithm>
    • 输入使用while (cin >> a ){ 算法主体 }
    • 输出使用cout,注意删除自己的测试输出,不能使用return,否则会一直报错语法错误
    #include <iostream>
    using namespace std;
    
    int main() {
        int a, b;
        while (cin >> a >> b) { // 注意 while 处理多个 case
            // 64 位输出请用 printf("%lld")
            cout << a + b << endl;
       }
    }
    
  2. 二维数组的初始化
    vector<vector<int>> dp(rows, vector<int>(cols, 0));// 注意要进行初始化
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            cin >> dp[i][j];// 不能使用push_back()进行处理
            
    }
    
  3. 输入一行以回车结尾的数字
    vector<int> vec;
    int tmp = 0;
    do {// 不能使用while(){},因为会丢失第一个输入
        cin >> tmp;
        vec.push_back(tmp);
    } while (cin.get() != '\n');
    

需要整理的基本输入https://zhuanlan.zhihu.com/p/494535515

cpp算法工具函数

概述

  1. 需要包含#include<algorithm>头文件
    • 作用:包含了对于容器的常用操作
    • 来源:大量基于迭代器的非成员模版函数
  2. 调用形式
    • 函数指针
    • 仿函数
    • 匿名函数
    	#include <iostream>     // std::cout
    	#include <algorithm>    // std::for_each
    	#include <vector>       // std::vector
    	 // 函数形式
    	void myfunction (int i) {  // function:
    	  std::cout << ' ' << i;
    	}
    	 // 仿函数形式
    	struct myclass {           // function object type:
    	  void operator() (int i) {std::cout << ' ' << i;}
    	} myobject;// 注意声明时就定义了类对象
    	// 匿名函数形式
    	auto anonymous_function = [](int i){
    		cout << i << ' ';
    	};
    	int main () {
    	  std::vector<int> myvector = {10, 20, 30};
    		
    	  for_each (myvector.begin(), myvector.end(), myfunction);
    	  for_each (myvector.begin(), myvector.end(), myobject);
    	  for_each (myvector.begin(), myvector.end(), anonymous_function);
    	  return 0;
    	}
    

基本工具函数

  1. for_each(iterator_start, iteratro_end, functor)
    • 输入
      • iterator_start:容器的起始迭代器,指向起始位置的指针
      • iteratro_end:容器的结束迭代器,指向结束位置的指针
      • functor:函数对象,如匿名函数、仿函数和函数指针等
      • 以下工具函数的调用参数含义均如上所示
    • 输出
      • 遍历指定容器迭代器范围内的元素,并交由functor进行处理
    • 其他
      • 函数对象的形参必须是指定的迭代容器元素类型
  2. find(iterator_start, iteratro_end, 子序列值)
    • 输出:返回迭代容器范围内匹配子序列值的起始位置迭代器
  3. count(ivec.begin() , ivec.end() , searchValue)
    • 输出:返回查询值出现的次数
  4. sort
  5. equal()
  6. search()
  7. swap()
  8. replace()
  9. remove()
  10. unique()
  11. sort()
  12. min()
  13. max()
// for_each的使用
vector<int> vec = {1, 2, 3, 4};
struct functor {
	void operator()(int i) { cout << i << ' ';}
}func;
for_each(vec.begin(), vec.end(), func);

// find函数的使用
string str = "hello world";
auto itr = find(str.begin(), str.end(), "ll");
if (it != str.end())
    cout << "查找成功";

// count函数的使用
string m = "1233445";
cout << count(m.begin(), m.end(),'3') << endl;

算法模板

基本函数模板

  1. 基本算法模型

    // 输入部分
    
    // 健壮性检查
    if (输入参数不符合情况) {
    	doing();
    	return false;
    }
    
    // 初始化:给工作变量赋初值,符合要求的第一次循环条件
    int initial_value = 0;// 会被算法初始化的也应该赋初值
    // 算法递推
    while (工作变量符合算法循环条件) {// 注意考虑最后不足算法增量的部分
    	doing();// 对结果序列操作的函数
    	工作变量的迭代;// 注意工作变量在使用完成后已经被污染
    }
    
    // 收尾
    处理不足最后一次算法增量的部分
    
  2. 优化(降低重复性)

    • 对于多次查找的情况,可以通过建表进行索引。
    • 对于多次重复的操作,可以封装一个匿名函数
  3. 数学归纳法(动态规划核心公式的推导)

    • 推导前五个简单的输入和输出,从而假设递进关系式
    • 再使用两个进行验证

函数式/无状态编程模板

  1. 基本理解的角度

    • 单向数据流:将多个函数连成“管道”,前一个函数的输出作为后一个函数的输入,依次传递,组成一个线性工作流
    • 流水线加工:将原始数据看作“原材料”,每个函数是对原材料的一次加工,使用函数流水线组成一条数据加工的生产线。
  2. 特点:

    • 不可变性:函数式编程通常需要使用不可变的数据结构,即不允许修改数据的原始状态。它强调通过创建新的数据结构来表示修改后的状态。

    • 惰性求值:函数式编程通常使用惰性求值,即只在需要时才求值。这样可以避免不必要的计算,提高程序的效率。

    • 无副作用:函数式编程也强调避免副作用,即函数执行不应该对外部环境产生影响。本质是函数内部不改变规定数据对象和规定动作范围外的状态。

    • 函数作为一等公民:函数与数据地位相同,相互独立(解决了代码本质也是数据)。函数可以像数据一样被传递,赋值和返回。这使得函数式编程具有高阶函数和函数组合等特性。
      在这里插入图片描述

      编程范式抽象对象特性
      面向过程计算的运行步骤数据+算法 = 程序
      面向对象实体的属性和动作对象的状态和改变自身状态的动作
      函数式数据和动作值经过动作映射成新值
  3. 设计高效的不可变的数据结构Chris Okasaki 的博士论文https://link.zhihu.com/?target=https%3A//www.cs.cmu.edu/~rwh/theses/okasaki.pdf

  4. 表观函数和状态转移函数。每一次迭代中,状态转移函数负责将当前这个状态变成下一个状态,而表观函数则负责将状态转化成用户需要看到的值,


状态机编程模板

  1. 面向对象,符合cpu处理的基本逻辑

常用容器

unordered_map

// 引入头文件
#include <unordered_map>
vector<int> vec = {1,1,3,4,5,5,5};
// 定义unordered_map对象
unordered_map<char, int> umap;
// 增加
for(const auto &i : vec){	// 将vector容器中的元素输入到unordered_map对象中
	umap[i]++;	// key:有键值i则将其值+1,没有则插入
}
// unordered_map中对于值的访问和更改
unordered_map<char, int>::iterator itr;
for(const auto &c : str){
    itr = umap.find(c);
    if(itr != umap.end())
        doing(itr->second);   
}

unordered_set

#include <unordered_set>
using namespace std;
// 定义对象
unordered_set<string> uset;
// 增加
uset.emplace("apple"); // 如果uset中含有相同元素则不添加
// 删除
uset.erase("orange");
// 查找
unordered_set<string>::iterator itr;
itr = uset.find("apple");
if (itr != uset.end()) {
   return  true;
}

输出字符相关转换

字符串的转换

  1. 字符转换成字符串
    char c = 'c';
    string s = "";
    // 1. 调用append函数
    s.append(1, c);
    // 2. 使用 += 
    s += c;
    
  2. int/float/double转换成字符串
     int i = 110;
     string s = "";
     s += to_string(i);
    
  3. 将字符串转换成int
    string str = "123";
    int num = stoi(str);
    
  4. 字符串截取
    string str = "Hello, World!";
    string sub_str = str.substr(7, 5);	// 从第7个开始截取后面5个字符(从0开始计数)
    cout << sub_str << endl; // 输出 "World"
    

字符串和十进制的转换

  1. atoiitoa函数
    // 注意需要包含的头文件
    #include <iostream>
    using namespace std;
    
     // string转换成char或者char*
     char ch[20];
     string s="123456";
     strcpy(ch,s.c_str());   // c_str()返回的const char *
     char* p=const_cast<char*>(a_str());
     // char *转换为string,直接赋值即可
     string s;
     char* p ="hello";
     s = p;
    
    // atoi()
    // 功能:字符串转换成十进制数
    // 特点:直到遇上数字或正负符号才开始做转换,
    // 	而再遇到 非数字 或 字符串结束时(’\0’) 才结束转换,并将结果返回
    const char *s = " 134";
    int num = atoi(s);
    cout << num; //输出:134 
    
    // itoa()
    // 功能:十进制转换成任意进制的字符串
    // 特点:将十进制转换成2~36中任意进制的字符串
    int num = 100;
    char str[25];
    itoa(num, str, 2);// 转换成2~36进制的字符串
    cout << str; //输出100 
    
    // strtol()
    // 功能:将一个任意2-36进制数转化为long型的10进制数
    char str[30] = "1000";
     char *substring;
     long number;
     number = strtol(str, &substring, 2);
    

进制数的输出格式

  1. 在C++语言(hex、oct、itoa)

    // 所需头文件
    #include <iostream>
    using namespace std;
    int num = 0;
    cin >> hex >> num;
    cin >> num;
    cin >> oct>> num;
    
    cout << hex <<num<< endl; 	// 十六进制
    cout << num <<endl;			// 十进制	
    cout << oct <<num<<endl;	// 八进制
    // 二进制
    char s[10]; //自定义二进制数的位数,输出位数是实际所需位数
    itoa(num,s,2);//转成字符串,进制为2
    cout << s <<endl;// 二进制
    
  2. 在C语言中

    printf("%x",35);    //按十六进制格式输出
    printf("%d",35);    //按十进制格式输出
    printf("%o",35);    //按八进制格式输出
    // 按二进制进行输出
    char s[10]; //自定义二进制数的位数,输出位数是实际所需位数
    itoa(num,s,2);//转成字符串,基数为2 
    printf("%s",s);
    

十进制的二级制形式运算

// 按位与&:全1为1
int AND = 1 & 2; // 01 & 10 = 0b00 = 0

// 按位或|:有1为1
int OR = 1 | 2; // 01 | 10 = 0b11 = 3

// 非运算~:int类型为16位全部取反
~6; // ~0000 0000 0000 0110 = 1111 1111 1111 1001  = 1000 0000 0000 0110+1(保留符号位,全部取反+1) = -7

// 异或运算^:不同为1
// a ^ b ^ a = b;
int XOR = 1 ^ 2; // 01 ^ 10 = 0b11 = 3

// 同或运算 ~(a ^ b):相同为1
int SAME_OR = ~(1 ^ 2); // ~(01 | 10) = 0

// 左移运算(oper << n):向左移1位,末尾添0。相当于十进制乘以2
3 << 1;     // 0000 0000 0000 0011 -> 0000 0000 0000 0110 = 3*2 = 6

// 右移运算(oper >> n):向右移1位
(-6 >> 1); // 相当于除以2


少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
不如点赞·收藏·关注一波


🚩点此跳转到首行↩︎

参考博客

  1. C++中的各种进制转换函数汇总
  2. 【C语言】 itoa()函数 和 atoi()函数(字符串与整型数的转换)
  3. 二分查找算法详解
  4. [杂谈] 3.#include algorithm 用法用途
  5. 函数式编程的核心价值
  6. 待定引用
  7. 待定引用
  8. 待定引用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逆羽飘扬

如果有用,请支持一下。

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

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

打赏作者

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

抵扣说明:

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

余额充值