⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)

目录

1.accumulate

2.__builtin_ctz / __builtin_ctzll

3.__builtin_clz / __builtin_clzll

3.__builtin_popcount

4.bitset

4.1 参数

4.2 构造函数

4.3 成员函数

4.4 bitset的应用

5.lower_bound / upper_bound

6.min_element / max_element

7.iota

8. next_permutation

9.  stringstream

持续更新中......


1.accumulate

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第1张图片

①求和:

第三个参数作为初始值,将区间[first, end)的值相加,返回初始值加上区间总和的值。

需要注意的是,如果总和超出区间中数的类型范围,可以将第三个参数强转成64位的long long类型

#include     
#include       // std::accumulate
#include        

int main() {
	int init = 0;
	std::vector nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	std::cout << std::accumulate(nums.begin(), nums.end(), init);  //output:55
	return 0;
}

②自定义:

第三个参数传入函数或者对象,自定义函数包含两个参数,第一个参数为初始值,第二个参数将依次传入范围中的值,具体看代码注释;如果是对象,可在在对象中重载operator()实现上述功能

#include     
#include       // std::accumulate
#include 

template
class myclass {
public:
	int operator()(T x, T y) { return x + 3 * y; }
};

int main() {
	int init = 0;
	std::vector nums = { 100, 200, 300};

	std::cout << std::accumulate(nums.begin(), nums.end(), init, [&](int x, int y) { return x + 2 * y; }) << std::endl;;  //output:55
	//output: 0 + 100 * 2 + 200 * 2 + 300 * 2 = 1200

	std::cout << std::accumulate(nums.begin(), nums.end(), init, myclass());
	//output: 0 + 100 * 3 + 200 * 3 + 300 * 3 = 1800
	return 0;
}

2.__builtin_ctz / __builtin_ctzll

__builtin系列的函数为GCC编译器的内联函数;

__builtin_ctz用于计算一个32位数中后导零的数量

cout << __builtin_ctz(16);  //16: 10000 --->  output:4

 __builtin_ctzll用于计算一个64位数中后导零的数量

cout << __builtin_ctzll(1LL << 40);   //output: 40

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第2张图片

3.__builtin_clz / __builtin_clzll

__builtin_clz :用于计算一个32位数前导零数量

cout << __builtin_clz(8);   //(0000 0000 0000 0000 0000 0000 0000 1000) --> output: 28
int LOG = 31 - __builtin_clz(8);   //LOG = 3 --> 2^3 = 8

对于一个不是2的幂的数,求它以2为底的对数,用上述第二段代码求得的是向下取整之后的值

int LOG = 31 - __builtin_clz(15);   //(0000 0000 0000 0000 0000 0000 0000 1111)   LOG = 3 

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第3张图片

__builtin_clzll:用于计算一个64位数前导零数量

3.__builtin_popcount

用于计算一个数的二进制中1的个数

cout << __builtin_popcount(15);   //output: 4

4.bitset

bitset类模拟了存放bool类型的array ,但是对其做了空间优化,每个元素0或1都只占用了一个位,并且可以用 [ ] 访问每一位的值

4.1 参数

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第4张图片

4.2 构造函数

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第5张图片

#include 
#include 
#include 
int main() {
		std::bitset<16> foo;                   
		std::bitset<16> bar(0xfa2);             
		std::bitset<16> baz("0101111001");     

		std::cout << foo;       //output:0000000000000000
		std::cout << bar;       //output:0000111110100010
		std::cout << baz;       //output:0000000101111001

		return 0;
}

4.3 成员函数

①set()

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第6张图片

用法:1.将所有位设置成1;  2.将指定位设置成0或1(默认为1)

②reset()

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第7张图片

用法:1. 将所有位设置成0 ; 2.将指定位设置成0;

③operator[]   

int main() {
	std::bitset<8> bs;
	for (int i = 0; i < bs.size(); i++) {
		bs[i] = 1;
	}
	std::cout << bs;     //output:  11111111
}

④count    返回1的个数

int main() {
	std::bitset<8> bs(15);
	std::cout << bs.count();   //output:  4;
}

⑤to_string      转为string类型 

 ⑥to_ullong     转为 unsigned long long类型

其他:​​​​​​​bitset - C++ Reference (cplusplus.com)

4.4 bitset的应用

① 快速擦找大量数据是否在一个集合总

② 求两个集合的交集

③操作系统中的磁盘块标记

④排序去重

5.lower_bound / upper_bound

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第8张图片

C++标准库自带的二分查找算法,对于lower_bound(val),函数返回 [first, last) 范围内val下限(第一个大于等于val)位置的迭代器,而upper_bound则是返回 [first, last) 范围内val上限(第一个大于val)位置的迭代器

#include      // std::cout
#include     // std::lower_bound, std::upper_bound, std::sort
#include        // std::vector

int main() {
	int myints[] = { 10,20,30,30,20,10,10,20 };
	std::vector v(myints, myints + 8);           // 10 20 30 30 20 10 10 20

	std::sort(v.begin(), v.end());                // 10 10 10 20 20 20 30 30

	std::vector::iterator low, up;
	low = std::lower_bound(v.begin(), v.end(), 20);          
	up = std::upper_bound(v.begin(), v.end(), 20);                   

	std::cout << "lower_bound at position " << (low - v.begin()) << '\n';    //output: 3
	std::cout << "upper_bound at position " << (up - v.begin()) << '\n';     //output: 6

	return 0;
}

需要注意的是,对于如vector这类支持随机迭代器的容器使用lower_bound/upper_bound函数的时间复杂度为logN, 而对于set/multiset这类不支持随机迭代器的容器,使用库函数的lower_bound/upper_bound函数的时间复杂度为N* logN

而set/multiset中也有实现二分查找的同名成员函数,时间复杂度为logN

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第9张图片
 

算法运用:有序集合 + 滑动窗口
2817. 限制条件下元素之间的最小绝对差

220. 存在重复元素 III

6.min_element / max_element

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第10张图片

返回区间 [first, last) 中最小值的迭代器

// min_element/max_element example
#include      // std::cout
#include     // std::min_element, std::max_element
#include 
int main() {
	std::vector arr = { 3,7,2,5,6,4,9 };

	// using default comparison:
	std::cout << "The smallest element is " << *std::min_element(arr.begin(), arr.end());
	std::cout << "The largest element is " << *std::max_element(arr.begin(), arr.end());

	return 0;
}

7.iota

见文章【C++】iota函数 + sort函数实现基于一个数组的多数组对应下标绑定排序_Dusong_的博客-CSDN博客


8. next_permutation

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第11张图片

按字典序的到全排类的下一个排列,如果函数可以将对象重新排列为字典上更大的排列,则返回 true。否则,该函数返回 false 以指示排列不大于前一个排列

#include      
#include     
#include 
using namespace std;
int main() {
    vector arr = { 2, 1, 3 };
    sort(arr.begin(), arr.end());   
    do {
        for (auto x : arr) cout << x << ' ';
        cout << endl;
    } while (next_permutation(arr.begin(), arr.end()));

    return 0;
}

⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第12张图片

 例题:leetcode 46.全排列

法一:回溯

class Solution {
public:
    vector> permute(vector& nums) {
        int n = nums.size();
        vector> ans;
        vector path(n), vis(n, false);
        function dfs = [&](int i) -> void {
            if (i == n) {
                ans.push_back(path);
                return;
            }
            for (int j = 0; j < n; j++) {
                if (!vis[j]) {
                    path[i] = nums[j];
                    vis[j] = true;
                    dfs(i + 1);
                    vis[j] = false;
                }
            }
        };
        dfs(0);
        return ans;
    }
};


法二:库函数

class Solution {
public:
    vector> permute(vector& nums) {
        sort(nums.begin(), nums.end());
        vector> ans;
        do {
            ans.push_back(nums);
        } while (next_permutation(nums.begin(), nums.end()));
        return ans;
    }
};

9.  stringstream

此类的对象使用包含字符序列的字符串缓冲区。可以使用成员 str 将此字符序列作为字符串对象直接访问。可以使用输入和输出流上允许的任何操作从流中插入和/或提取字符。

这么说可能不太好懂,我们直接上例子⬇️

通过这一点我们可以很简单的实现输入字符串的分割操作

#include        // std::string
#include        // std::vector
#include      // std::cout
#include       // std::stringstream
using namespace std;

int main() {
	stringstream ss("I am Dusong!");
	vector output;
	string s = "";
	while (ss >> s) {
		output.push_back(s);
	}
	for (string& s : output) {
		cout << s << endl;
	}
	return 0;
}

 输出:⌈C++⌋accumlate、__builtin_、next_permutation等各类用于解算法题的库函数与类模板(持续更新中~)_第13张图片

继承关系

 有了这样的继承关系,你可以使用所有父类的public成员函数

(详细见stringstream-C++ Referance)

持续更新中......​​​​​​​

你可能感兴趣的:(C++,算法,c++,数据结构)