# 蓝桥杯（C/C++）知识点------杂

5 篇文章 0 订阅

## 蓝桥杯知识点（杂）

### 一、二分查找

#### 1、普通的二分查找

/*
[1,mid],[mid+1,size]
*/

int BinarySelect(int* arr, int n, int target) {
int left = 0;
int right = n - 1;
while (left <= right) {
int mid = (left + right) >> 1;
if (arr[mid] > target) {
right = mid - 1;
}
else if (arr[mid] < target) {
left = mid + 1;
}
else {
return mid;
}
}

return -1;
}

int main() {

int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

int n = sizeof(arr) / sizeof(int);
//所找的元素，则我们返回的就是他的下标
int target = 8;

int index = BinarySelect(arr, n, target);

printf("index = %d\n", index);

return 0;
}


/*
[1,mid-1],[mid,size]

*/

int BinarySelect(int* arr, int n, int target) {
int left = 0;
int right = n - 1;
while (left < right) {
int mid = (left + right) >> 1;
if (arr[mid] > target) {
right = mid;
}
else if (arr[mid] < target) {
left = mid + 1;
}
else {
return mid;
}
}

return -1;
}

int main() {

int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

int n = sizeof(arr) / sizeof(int);
//所找的元素，则我们返回的就是他的下标
int target = 10;

int index = BinarySelect(arr, n, target);

printf("index = %d\n", index);

return 0;
}


#### 2、二分查找的列题

Demo：

#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>

//数组中的数为num,要查找的数是x
bool isBlue1(int num, int x) {
if (num < x) {
return true;
}
else {
return false;
}
}

//数组中的数为num,要查找的数是x
bool isBlue2(int num, int x) {
if (num <= x) {
return true;
}
else {
return false;
}
}

int binary_select1(int* arr,int n,int x) {
int left = -1, right = n;
while (left + 1 != right) {
int mid = (left + right) >> 1;
if (isBlue1(arr[mid], x)) {
left = mid;
}
else {
right = mid;
}
}
if (arr[right] == x) {
return right;
}
else {
return -1;//找不到返回-1
}
}

int binary_select2(int* arr,int n,int x) {
int left = -1;
int right = n;

while (left + 1 != right) {
int mid = (left + right) >> 1;
if (isBlue2(arr[mid],x)) {
left = mid;
}
else {
right = mid;
}
}

if (arr[left] == x) {
return left;
}
else {
return -1;//找不到返回-1
}
}

int main() {

int arr[] = { 0 };
//n为数组中的元素的个数，q为要查询元素的个数
int  n, q;
scanf("%d %d", &n, &q);

for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}

//x表示就是要查询的数
int x;

while (q--) {
scanf("%d", &x);

//index1就是要查询的数第一次出现的位置（下标）
int index1 = binary_select1(arr, n, x);
//index2就是要查询的数最后一次出现的位置（下标）
int index2 = binary_select2(arr, n, x);

printf("index1 = %d , index2 = %d\n", index1, index2);
}
return 0;
}


#### 3、浮点数的二分查找

/*

*/
#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>

int n = 0;

bool check(double mid) {
if (mid * mid * mid <= n) {
return true;
}
else {
return false;
}
}

int main() {

scanf("%d", &n);

double left = -100, right = 100;
while (right - left > 1e-8) {
double mid = 1.0*(left + right) / 2;

if (check(mid)) {
left = mid;
}
else {
right = mid;
}
}

printf("%lf\n", left);
printf("%lf\n", right);

return 0;
}



### 二、二进制

int main() {

int BinaryNum = 0;
scanf("%d", &BinaryNum);

int count = 0;

while (BinaryNum) {
//在底层是用的补码进行&运算，&：表示两个1才为1，其他就是0
if (BinaryNum & 1 == 1) {
count++;
}
BinaryNum = BinaryNum >> 1;

}

printf("count = %d\n", count);
return 0;
}


int main() {

int BinaryNum = 0;
scanf("%d", &BinaryNum);

//你想知道第几位的值
int k = 3;

printf("%d\n", BinaryNum>>(3-1)&1);
return 0;
}


### 三、前缀和

#### 1、快速求出两个区间的数的总和

Demo：

#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(){
int num = 0;
int seekNum = 0;
int arr[] = { 0 };
int sum = 0;
scanf("%d%d", &num, &seekNum);

for (int i = 0; i < num; i++) {
scanf("%d", &arr[i]);
}

while (seekNum--) {
int left = 0;
int right = 0;
scanf("%d%d", &left, &right);
sum = 0;
for (int i = left; i <= right; i++) {
sum += arr[i];
}
printf("sum = %d\n", sum);
}
return 0;
}


#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main(){
int num = 0;
int seekNum = 0;
int arr[] = { 0 };
int sum[] = {0};
scanf("%d%d", &num, &seekNum);

for (int i = 1; i <= num; i++) {
scanf("%d", &arr[i]);
//使用sum数组将每一个数的前缀和保存起来
sum[i] = sum[i - 1] + arr[i];
}

while (seekNum--) {
int left = 0;
int right = 0;
scanf("%d%d", &left, &right);
//这里看不懂的，可以画一个数组，再根据代码细看
printf("sum = %d\n", sum[right]-sum[left-1]);
}
return 0;
}



#### 2、再二维数组中使用前缀和求出两个坐标点之间的元素的总和

Demo：

#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>

int main(){
int row = 0;
int col = 0;
int seekNum = 0;
int arr[][10000] = { 0 };
int sum[][10000] = { 0 };

scanf("%d%d%d", &row, &col, &seekNum);

for (int i = 1; i <= row; i++) {
for (int j = 1; j <= col; j++) {
scanf("%d", &arr[i][j]);
sum[i][j] = arr[i][j] + sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1];
}
}

while (seekNum--) {
int x1, x2, y1, y2;
scanf("%d%d%d%d", &x1, &x2, &y1, &y2);

printf("sum = %d\n", sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1]);
}

return 0;
}


#### 3、给定一个目标值，在两个数组中分别使用一个元素，让这两个数的和等于这个目标值

Demo：（不知道为什么我的会超出数组范围）

#define  _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>

int main(){
int arr1[] = { 0 };
int arr2[] = { 0 };
int num1 = 0;
int target = 0;
int num2 = 0;

scanf("%d%d%d", &num1, &num2, &target);

for (int i = 0; i < num1; i++) {
scanf("%d", &arr1[i]);
}

for (int j = 0; j < num2; j++) {
scanf("%d", &arr2[j]);
}

for (int i = 0, j = num2 - 1; i < num1; i++) {
while (j >= 0 && arr1[i] + arr2[j] > target) {
j--;
}

if (arr1[i] + arr2[j] == target) {
printf("index1 = %d,index2 = %d\n", i, j);
return 0;
}

}
return 0;
}


### 四、双指针

#### 1、递增三元组

给定三个整数数组

A=[A1,A2,…AN]
,
B=[B1,B2,…BN]
,
C=[C1,C2,…CN]
,

满足：

1≤i,j,k≤N
Ai<Bj<Ck

。

个整数 A1,A2,…AN
。

个整数 B1,B2,…BN
。

个整数 C1,C2,…CN
。

1≤N≤105
,
0≤Ai,Bi,Ci≤105

3
1 1 1
2 2 2
3 3 3

27


==思路分析1：==在这道题中可以使用我们之前提到的二分查找法，就是将去遍历中间的那个数，使中间的这个数满足题目的要求

### 五、关于DFS（深度优先算法）

#### 1、全排列问题

题目描述

1 到 n 所有不重复的排列，即 n 的全排列，要求所产生的任一数字序列中不允许出现重复的数字。

n。

5
5 个场宽。

3

1    2    3
1    3    2
2    1    3
2    3    1
3    1    2
3    2    1


Demo：

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 10;
bool st[N];//true表示选过这个数，false表示没有选过这个数

int arr[N];//存的是答案，即{1,2,3}
int n = 0;

void dfs(int x) {//x是当前枚举到了数组的哪个位置
if (x > n) {
for (int i = 1; i <= n; i++) {
printf("%5d", arr[i]);
}
printf("\n");
return;
}
for (int i = 1; i <= n; i++) {
if (!st[i]) {
st[i] = true;//就是选了这个数
arr[x] = i;//让数组记录下这个数
dfs(x + 1);//再进行选择下一个数
st[i] = false;//再把状态置空，即当回溯时，会回到上一个状态
arr[x] = 0;
}
}
}

int main() {
scanf("%d", &n);
dfs(1);
return 0;
}



#### 2、组合的输出

题目描述

123
,
124
,
125
,
134
,
135
,
145
,
234
,
235
,
245
,
345
123,124,125,134,135,145,234,235,245,345。

3
3 个场宽。以 C++ 为例，你可以使用下列代码：

cout << setw(3) << x;

5 3

1  2  3
1  2  4
1  2  5
1  3  4
1  3  5
1  4  5
2  3  4
2  3  5
2  4  5
3  4  5


Demo

 #define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

int n, r;
const int N = 21;
int arr[N];

/*
int x;//记录枚举到了哪个位置
int arr[];//用来记录存了哪些数据
int start;//用来记录当前位置从几开始枚举·
*/

void dfs(int x, int start) {
//退出搜索
if (x > r) {
for (int i = 1; i <= r; i++) {
printf("%3d", arr[i]);
}
printf("\n");
return;
}

for (int i = start; i <= n; i++) {
arr[x] = i;
dfs(x + 1, i + 1);
arr[x] = 0;
}
}

int main() {
scanf("%d%d", &n, &r);

dfs(1,1);

return 0;
}



#### 3、跳台阶

1≤n≤15

##### 输入样例：
5

##### 输出样例：
8


Demo：

#include <stdio.h>

int dfs(int n){
if(n==1){
return 1;
}else if(n==2){
return 2;
}else{
return dfs(n-1)+dfs(n-2);
}

}

int main(){

int n = 0;
int ret = 0;
scanf("%d",&n);
ret = dfs(n);
printf("%d",ret);
return 0;
}


#### 4、递归实现指数型枚举

1≤n≤15

##### 输入样例：
3

##### 输出样例：
解释
3
2
2 3
1
1 3
1 2
1 2 3


Demo：

#include<iostream>
using namespace std;

const int N = 21;
int st[N];//记录状态 ，1表示选，2表示不选，0表示还在考虑
int n;

void dfs(int x){

if(x>n){
int i = 0;
for(int i=1;i<=n;i++){
if(st[i]==1){
printf("%d ",i);
}

}
printf("\n");
return;
}

//不选
st[x] = 2;
dfs(x+1);
st[x] = 0;//恢复现场

//选
st[x] = 1;
dfs(x+1);
st[x] = 0;//恢复现场

}

int main()
{
scanf("%d",&n);
dfs(1);
return 0;
}


#### 5、递归实现排列型枚举

##### 输入输出样例

**输入 **

3


**输出 **

    1    2    3
1    3    2
2    1    3
2    3    1
3    1    2
3    2    1

##### 说明/提示

1≤n≤9。

Demo：

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 10;
bool st[N];//true表示选过这个数，false表示没有选过这个数

int arr[N];//存的是答案，即{1,2,3}
int n = 0;

void dfs(int x) {//x是当前枚举到了数组的哪个位置
if (x > n) {
for (int i = 1; i <= n; i++) {
printf("%5d", arr[i]);
}
printf("\n");
return;
}
for (int i = 1; i <= n; i++) {
if (!st[i]) {//表示如果这个数没有被选过就选择它
st[i] = true;
arr[x] = i;
dfs(x + 1);
st[i] = false;
arr[x] = 0;
}
}
}

int main() {
scanf("%d", &n);
dfs(1);
return 0;
}



#### 6、递归实现组合型枚举

##### 题目描述

123,124,125,134,135,145,234,235,245,345123,124,125,134,135,145,234,235,245,345。

##### 输出格式

cout << setw(3) << x;


##### 输入输出样例

**输入 **

5 3


**输出 **

  1  2  3
1  2  4
1  2  5
1  3  4
1  3  5
1  4  5
2  3  4
2  3  5
2  4  5
3  4  5


Demo：



#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

int n, r;
const int N = 21;
int arr[N];

/*
int x;//记录枚举到了哪个位置
int arr[];//用来记录存了哪些数据
int start;//用来记录当前位置从几开始枚举·
*/

void dfs(int x, int start) {
//退出搜索
if (x > r) {
for (int i = 1; i <= r; i++) {
printf("%3d", arr[i]);
}
printf("\n");
return;
}

for (int i = start; i <= n; i++) {
arr[x] = i;
dfs(x + 1, i + 1);
arr[x] = 0;
}
}

int main() {
scanf("%d%d", &n, &r);

dfs(1,1);

return 0;
}



### 六、关于蓝桥杯中常用的STL

##### ①vector容器
#define _CRT_SECURE_NO_WARNINGS

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

int main() {
//创建一个int类型的vector数组，记得要包含头文件
vector<int> arr;

/*
还有其他的定义方法：
vector<int> a(3);//定义一个长度为3的vector  未初始化 输出》0 0 0

vector<int> a(10, 3); //定义一个长度为10，且每个数赋值为3

//将向量b中从下标0 1 2（共三个）的元素赋值给a，a的类型为int型
//它的初始化不和数组一样
vector<int>a(b.begin(),b.begin+3);

int b[7] = { 1,2,3,4,5,6,7 };
vector<int> a(b, b + 7);//给a赋值1-7的数值
*/

//尾插进去数据
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
arr.push_back(4);
arr.push_back(5);

//遍历数组中的元素，使用迭代器
vector<int>::iterator it;
for (it = arr.begin(); it != arr.end(); it++)
printf("%d ", *it);

//在任意的位置插入元素,在第i+1个元素前面插入数据10，即在第二个元素前面插入数据10
arr.insert(arr.begin() + 1, 10);//1 10 2 3 4 5

//删除元素：
arr.erase(arr.begin() + 2); //删除第i+1个元素,即删除第三个元素

arr.erase(arr.begin() + 0, arr.end() + 4); //删除区间[i, j - 1]; 区间从0开始

//删除尾部元素
arr.pop_back();

//求数组大小:
arr.size();

//清空
arr.clear();

return 0;
}



###### （1）排序
//关于在vector中使用排序的方法，也是有直接封装好了的方法，直接可以调用
//注意使用<algorithm>头文件

#define _CRT_SECURE_NO_WARNINGS

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

int main() {
vector<int> arr = { 10,4,1,0,3,7,8 };
sort(arr.begin(),arr.end());

vector<int>::iterator it;
for (it = arr.begin(); it != arr.end(); it++) {
printf("%d ", *it);
}

return 0;
}


###### （2）逆序
//
#define _CRT_SECURE_NO_WARNINGS

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

int main() {
vector<int> arr = { 1,2,3,4,5 };

reverse(arr.begin(), arr.end()); //将元素翻转，即逆序排列！

vector<int>::iterator it;
for (it = arr.begin(); it != arr.end(); it++) {
printf("%d ", *it);
}

return 0;
}


##### ②map容器（有序的但是可以重复）



##### ③set容器（有序但是不重复）
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <set>
#include <algorithm>

using namespace std;

int main() {
//创建一个set数组
set<int> s;
//插入数据，并且自动根据数据的大小进行排序
s.insert(10);
s.insert(40);
s.insert(20);
s.insert(40);
s.insert(90);
s.insert(60);
//遍历set
set<int>::iterator it;
for (it = s.begin(); it != s.end(); it++) {
printf("%d ", *it);
}
printf("\n");
//删除起始位置的元素
s.erase(s.begin());

//根据元素删除
s.erase(40);

//查找元素是否存在，存在就返回它的迭代器，不存在就返回set.end();
set<int>::iterator ret = s.find(90);
printf("%d", *ret);

//查找元素的个数
int count = s.count(60);

//清空
s.clear();
return 0;
}


##### ④队列

queue<Type, Container> (<数据类型，容器类型>）

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <queue>
#include <list>
#include <algorithm>

using namespace std;

int main() {

/*默认为用deque容器实现的queue
queue<int> q1;
queue<double> q2;
queue<char> q3;
*/

//用list容器实现的queue
queue<char, list<char>> q1;

//注意：不能使用vector去初始化队列

//push() 在队尾插入一个元素
q1.push(10);
q1.push(20);
q1.push(30);
q1.push(40);
q1.push(50);

//pop() 删除队列第一个元素
q1.pop();

//size() 返回队列中元素个数
int size = q1.size();

//empty() 如果队列空则返回true
bool flag = q1.empty();

//front() 返回队列中的第一个元素
int first = q1.front();

//back() 返回队列中最后一个元素
int tail = q1.back();

//遍历队列
for (int i = 0; i < size; i++) {   //myqueue_size 必须是固定值
printf("%d ", q1.front());
/*q1.push(q1.front());*/
q1.pop();
}

return 0;
}



### 七、c++中常用的数学函数

	//求常数e的x次方。#define e 2.71828182845904523536
exp(x);
//求x的y次方
pow(x, y);
//开平方
sqrt(x);

//求e为底的对数 ln
log(x);
//求10为底的对数 lg
log10(x);
//求x为底的y的对数
log(y) / log(x);

//整数型的绝对值
int abs(x);
//浮点型的绝对值
double fabs(double x);

//向上取整 返回的是大于或等于x的最小整数
ceil(x);

//向下取整 返回的是小于或等于x的最大整数
floor(x);

//朝零方向取整
fix(x);

//四舍五入到最近的整数
round(x);

//使用round保留2位小数
double num = 3.1415926;
double roundedNum = round(num * 100) / 100;
cout << roundedNum << endl;     //输出 3.14

//产生一个在[0,50)区间内的随机数
r = rand() % 50;
//产生[a,b]区间的随机数
r = a + rand() % (b-a+1);

//三角函数
sin(x);    //正弦
cos(x);    //余弦。cos(π)=-1,故 π = acos(-1)
tan(x);    //正切

//反三角函数
asin(x);    //反正弦 [−π/2, π/2]
acos(x);    //反余弦 [0, π]
atan(x);    //反正切（主值）   [−π/2, π/2]
atan2(x);    //反正切（整圆值） [−π, π]

//两个数比较
min(a, b, comp);    //取最小值，comp为指定的比较规则，可缺省
max(a, b, comp);

//多个数比较，需加 { }
min({a,b,c,d}, comp);

辗转相除法求最大公约数：

int gcd(int a,int b){

int temp;

while(a%b!=0){

temp=a;

a=b;

b=temp%b;

}

return b;

}

辗转相除法最小公倍数：

int lcm(int a,int b){

int a1=a,b1=b,temp;

while(a%b!=0){

temp=a;

a=b;

b=temp%b;
}
return a1/b*b1;
}

杨辉三角：
任意一行的所有元素

C[0]=1;

For(int i=1;i<=n;i++)
C[i]=C[i-1]*(n-i+1)/


### 八、常考知识点

#### 1、优先队列

Demo：这里默认使用的是大顶堆

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <queue>
#include <list>
#include <algorithm>

using namespace std;

int main() {
//定义一个存储int型的优先队列
priority_queue<int> queue;//大顶堆

//向队列中插入元素
queue.push(1);
queue.push(-3);
queue.push(0);
queue.push(5);
queue.push(8);
queue.push(10);

//获取元素的数量
int size = queue.size();

//删除优先级最高的元素
queue.pop();

//访问优先级最高的元素
queue.top();

//0判断优先队列是否为空
bool flag = queue.empty();

while (!queue.empty()) {
printf("%d ", queue.top());
queue.pop();
}
return 0;
}



Demo：小顶堆

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <queue>
#include <list>
#include <algorithm>

using namespace std;

int main() {
//定义一个存储int型的优先队列
priority_queue<int,vector<int>,greater<int>> queue;//就改成了小顶堆，大顶堆是less<int>

//向队列中插入元素
queue.push(1);
queue.push(-3);
queue.push(0);
queue.push(5);
queue.push(8);
queue.push(10);

//获取元素的数量
int size = queue.size();

//删除优先级最高的元素
queue.pop();

//访问优先级最高的元素
queue.top();

//0判断优先队列是否为空
bool flag = queue.empty();

while (!queue.empty()) {
printf("%d ", queue.top());
queue.pop();
}
return 0;
}


• 30
点赞
• 25
收藏
觉得还不错? 一键收藏
• 打赏
• 4
评论
07-31 429
04-01 388
11-17
12-16 113
03-16 761
04-14 2696
04-15 2万+

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

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