数据结构题目2024

个人复习自用 

目录

希尔排序的间隔

 三元组表示的稀疏矩阵的乘法运算

 根据next数组推导模式字符串

村庄是否连通

 求整数最大间隔-性能

 表达式求值

判断布尔矩阵的奇偶性

求最大收益 

 三元组表示的稀疏矩阵的乘法运算

哈夫曼树A

linux路径

有序线性表合并

基数排序

创建RB树

约瑟夫环问题

工程最短消耗

判断是否为堆-堆整理

判断排序方法

旋转的矩阵

字符串应用-实现KMP匹配算法

互斥字符串

二叉树遍历及二叉树高度

多源最短路径

完全二叉树的先序遍历

创建AVL树并判断是否为完全二叉树

二元一次多项式求幂

Dijkstra单源最短路径 


希尔排序的间隔

题目描述

假设输入的序列为希尔排序的中间结果,请输出当前序列的最小间隔。

Input Format

输入N 0<N<=20。

随后输入N个整数

Output Format

序列排序的最小间隔 

样例输入输出

样例1

输入:

3
1 2 3

输出:

1

样例2

输入:

15
18 13 5 9 10 9 19 24 17 20 17 9 20 24 21

输出:

6

代码 

#include<bits/stdc++.h>
using namespace std;
bool isSorted(int* data, int gap, int index,  int size){
    bool sorted = true;
    int pos = index;
    while(pos + gap< size){
        if(data[pos] > data[pos + gap]){
            return false;
        }
        pos += gap;
    }
    return true;
}

bool isSorted(int* data, int gap, int size){
    bool sorted = true;
    int pos = 0;
    int groupId = 0;
    //分组判断
    for(groupId; groupId<gap;++groupId){
        if(!(isSorted(data, gap, groupId,size)))
            return false;
    }
    return true;
}

int main(){
    int n;
    cin >> n;
    int *data = new int[n];
    for(int i = 0; i<n;++i){
        cin >> data[i];
    }

    int gap = 1;
    for(gap;gap<=n; gap++){
        if(isSorted(data, gap, n)){
            break;
        }
    }
    cout << gap;
}

 三元组表示的稀疏矩阵的乘法运算

题目描述

对两个由三元组表示的稀疏矩阵进行乘法运算

输入:

第一行为三个整数row,column,count,用空格分隔,分别表示稀疏矩阵的行数、列数、非零元素的个数。

第二行开始输入该稀疏矩阵的三元组,每行三个整数,空格分隔,分别代表一个非零元素的行标、列标、值,共输入count行。

空一行后开始输入第二个稀疏矩阵的row,column,count,及三元组。

输出:

如果计算结果为零矩阵,输出“The answer is a Zero Matrix”,如果结果为非零矩阵,输出结果的三元组表示,要求输出三元组有序。如果无法计算矩阵乘法,输出“ERROR”。

样例输入输出

样例1

输入:

2 2 2
1 1 1
2 2 1

2 2 2
1 2 2
2 1 2

输出:

1 2 2
2 1 2

样例2

输入:

2 2 1
1 1 5

2 2 1
2 2 -5

输出:

The answer is a Zero Matrix

样例3

输入:

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

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

输出:

ERROR

代码

#include <bits/stdc++.h>
using namespace std;

struct Element {
	int row;
	int col;
	int value;
};

vector<Element> multiplySparseMatrices(const vector<Element>& mat1, const vector<Element>& mat2, int row1, int col1, int col2) {
	vector<Element> result;
	vector<vector<int>> intermediate(row1, vector<int>(col2, 0));
	
	for (const auto& elem1 : mat1) {
		for (const auto& elem2 : mat2) {
			if (elem1.col == elem2.row) {
				intermediate[elem1.row - 1][elem2.col - 1] += elem1.value * elem2.value;
			}
		}
	}
	
	for (int i = 0; i < row1; ++i) {
		for (int j = 0; j < col2; ++j) {
			if (intermediate[i][j] != 0) {
				result.push_back({i + 1, j + 1, intermediate[i][j]});
			}
		}
	}
	
	return result;
}

int main() {
	int row1, col1, count1;
	cin >> row1 >> col1 >> count1;
	
	vector<Element> mat1(count1);
	for (int i = 0; i < count1; ++i) {
		cin >> mat1[i].row >> mat1[i].col >> mat1[i].value;
	}
	
	int row2, col2, count2;
	cin >> row2 >> col2 >> count2;
	
	vector<Element> mat2(count2);
	for (int i = 0; i < count2; ++i) {
		cin >> mat2[i].row >> mat2[i].col >> mat2[i].value;
	}
	
	if (col1 != row2) {
		cout << "ERROR" << endl;
	} else {
		vector<Element> result = multiplySparseMatrices(mat1, mat2, row1, col1, col2);
		
		if (result.empty()) {
			cout << "The answer is a Zero Matrix" << endl;
		} else {
			sort(result.begin(), result.end(), [](const Element& a, const Element& b) {
				if (a.row == b.row) {
					return a.col < b.col;
				}
				return a.row < b.row;
			});

			for (const auto& elem : result) {
				cout << elem.row << " " << elem.col << " " << elem.value << endl;
			}
		}
	}
	
	return 0;
}

 根据next数组推导模式字符串

题目描述

根据KMP算法的next数组值,推断模式字符串。

假设模式字符串中只存在0,1两种字符。给出首字符和next数组。请输出模式字符串。如果next数组不合法则输出ERROR

Input Format

先输入模式字符串首字符0或者1,然后输入尾字符0或者1

再输入 模式字符串长度n,n<=30

最后输入n个以 -1,0,起始的整数。

Output Format

模式字符串 或者 ERROR 

说明

以传统未优化的KMP算法推导的next数组。

样例输入输出

样例1
输入:
1 1 6

-1 0 0 0 0 0
输出:
100001
样例2
输入:
1 1 6
-1 0 2 0 0 0
输出:
ERROR
样例3
输入:
1 1 7
-1 0 1 2 3 4 2
输出:
ERROR

代码

#include<iostream>
using namespace std;
int main()
{
	int begin, end, len;
	cin >> begin >> end >> len;
	int* p = new int[len];
	int* pNext = new int[len];
	p[0] = begin;
	p[len - 1] = end;
	int val;
	for (int i = 0; i < len; i++)
	{
		cin >> val;
		pNext[i] = val;
	}
	
	for (int i = 2; i < len; i++)
	{
		if (pNext[i] == 0)
		{
			if (p[0] == 1)
				p[i - 1] = 0;
			if (p[0] == 0)
				p[i - 1] = 1;
		}
		else if (pNext[i] - pNext[i - 1] == 1)
		{
			p[i - 1] = p[pNext[i] - 1];
		}
		else if (pNext[i] > i || (pNext[i] - pNext[i - 1] != 1 && p[i - pNext[i] - 1] == p[0])|| pNext[i] - pNext[i - 1] >1)
		{
			cout << "ERROR" << endl;
			delete[]p;
			delete[]pNext;
			return 0;
		}
		
	}

	for (int i = 0; i < len; i++)
	{
		cout << p[i];
	}
	delete[]p;
	delete[]pNext;
	return 0;
}

村庄是否连通

题目描述

村庄中存在一些路,根据输入的相邻村庄的路,判断某两个村庄是否能够联通。n个村庄使用0到n-1的不同整数标识。路使用取值范围【0,n-1】的整数对表示。例如 3 5,代表村庄3和5之间有一条路。

Input Format

村庄个数 n, 0<n<=20

路的条数 m,0<m<=50

m条路,即为2m个范围在【0,n-1】的整数   

需要判断是否相连的村庄对数 p 0<p<=10

需要判断是否相连的p对村庄,即为2p个范围在【0,n-1】的整数。

Output Format

能够连通输出

true

不可连通输出

false

样例输入输出

样例1

输入:

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

输出:

false
true

代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100

int fa[MAXN];

void init(int n){
	for(int i = 1; i<=n;++i) fa[i]=i;	//路径压缩
}

int find(int x){
	if(x == fa[x]) return x;
	else {
		fa[x] = find(fa[x]);
		return fa[x];
	}
	
}

void unionn(int i, int j){
	int i_fa = find(i);
	int j_fa = find(j);
	fa[i_fa] = j_fa;
}

int main(){
	int n, m, x,y,p;
	
	cin >> n;
	init(n);
	cin >> m;
	for(int i = 1; i<=m;++i){
		cin >> x >> y;
		unionn(x,y);
	}
	cin >> p;
	bool result[p];
	for(int i = 1; i<=p; ++i){
		cin >> x >> y;
		result[i] = (find(x) == find(y));
	}
	for(int i = 1; i <=p; ++i)
		cout << (result[i]? "true" : "false") << endl;
	
	return 0;
}

 求整数最大间隔-性能

题目描述

请输出数字序列的最大间隔。

请使用以下伪随机数生成函数 rand32 () 生成伪随机数

int  seed  ;
int rand(){ return((( seed   =  seed   * 214013L + 2531011L) >> 16) & 0x7fff); }
int rand32(){
return ((rand() << 16) + (rand() << 1) + rand() % 2);
}

Input Format

2个整数,n seed 其中 2<n<=20000000,seed为随机数种子。

Output Format

整数序列的最大间隔

Example

Input

2000000
1

Output

15737

注意:O(nlogn)以上的时间复杂度至少会有一个案例超时。

样例输入输出

样例1

输入:

1959000 4910

输出:

16709

代码

#include <iostream>
#include <algorithm>

using namespace std;

int n, seed;

// 生成伪随机数
int rand() {
	return (((seed = seed * 214013L + 2531011L) >> 16) & 0x7fff);
}

int rand32() {
	return ((rand() << 16) + (rand() << 1) + rand() % 2);
}

// 计算数字序列的最大间隔
int maxGap(int nums[]) {
	int maxgap = 0;
	int numsmax = nums[0], numsmin = nums[0];
	// 找到数组中的最大、最小值
	for (int i = 0; i < n; i++) {
		numsmax = max(numsmax, nums[i]);
		numsmin = min(numsmin, nums[i]);
	}
	
	if (numsmax == numsmin) return 0;
	
	bool* bucket = new bool[n](); // 初始化为false
	int* imax = new int[n]();
	int* imin = new int[n]();
	
	double gap = double(numsmax - numsmin) / (n - 1);
	
	// 通过散列,将各点归入对应的桶;在各桶中动态记录最大、最小值
	for (int i = 0; i < n; i++) {
		int index = ((nums[i] - numsmin) / gap);
		if (!bucket[index]) {
			imax[index] = nums[i];
			imin[index] = nums[i];
			bucket[index] = true;
		} else {
			imax[index] = max(nums[i], imax[index]);
			imin[index] = min(nums[i], imin[index]);
		}
	}
	
	int lastmax;
	for (int i = 0; i < n; i++) {
		if (bucket[i]) {
			lastmax = imax[i];
		}
	}
	
	// 计算相邻(非空)桶之间的最大间隔
	for (int i = 1; i < n; i++) {
		if (bucket[i]) {
			int tem = max(imin[i] - lastmax, imax[i] - imin[i]);
			maxgap = max(maxgap, tem);
			lastmax = imax[i];
		}
	}
	
	delete[] bucket;
	delete[] imax;
	delete[] imin;
	
	return maxgap;
}


int main() {
	cin >> n >> seed;
	if(n <=2 || n > 20000000) return 1;
	int* randomArray = new int[n];
	for (int i = 0; i < n; i++)
		randomArray[i] = rand32();
	
	// 计算并输出最大间隔
	cout << maxGap(randomArray) << endl;
	
	// 释放动态分配的内存
	delete[] randomArray;
	
	return 0;
}

 表达式求值

题目描述

设计一个表达式求值的程序。该程序必须可以接受包含(,),+,-,*,/,%和^(求幂)的中缀表达式,并求出结果。如果表达式正确,则输出表达式的值,如果表达式非法,则输出错误信息。
注意2^2^3转为后缀应为223^^

操作数均转为double运算。

幂运算可以直接使用pow(a,b)

%,操作数转为Int再进行计算。

输入要求:

多个表达式,每个表达式占一行。

输出要求:

对每个表达式,如果为正确表达式则输出结果(精确到小数点后两位),如果为错误表达式则输出“ERROR IN INFIX NOTATION”.

 

样例输入输出

样例1

输入:

(2-4)^3

输出:

-8.00

样例2

输入:

(3*5*(4+8)%2)

输出:

0.00

样例3

输入:

1+2(

输出:

ERROR IN INFIX NOTATION

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cmath>
#include <iomanip>
using namespace std;
 
char s[1000];
int  g_pos;  // 字符数组的下标
 
/* 字符转数字 */
double Translation(int & pos)
{
    double integer = 0.00;    // 整数部分
    double remainder = 0.00;  // 小数部分
 
    while (s[pos] >= '0' && s[pos] <= '9')
    {
        integer *= 10;
        integer += (s[pos] - '0');
        pos++;
    }
 
    if (s[pos] == '.')
    {
        pos++;
        int c = 1;
        while (s[pos] >= '0' && s[pos] <= '9')
        {
            double t = s[pos] - '0';
            t *= pow(0.1, c);
            c++;
            remainder += t;
            pos++;
        }
    }
 
    return integer + remainder;
}
 
/* 返回运算符级别 */
int GetLevel(char ch)
{
    switch (ch)
    {
    case '+':
    case '-':
        return 1;
    case '*':
    case '/':
        return 2;
    case '^':
    case '%':
    	return 3;
    case '(':
        return 0;
    case '#':
        return -1;
    };
}
 
/* 对两个数进行运算 */
double Operate(double a1, char op, double a2)
{
	int a = a1;
    int b = a2;
    switch (op)
    {
    case '+':
        return a1 + a2;
    case '-':
        return a1 - a2;
    case '*':
        return a1 * a2;
    case '/':
        return a1 / a2;
    case '%':
    	return a % b;
    case '^':
    	return pow(a1,a2);
    };
}
 
/* 利用两个栈进行模拟计算 */
double Compute()
{
    stack<char> optr;    // 操作符栈
    stack<double> opnd;  // 操作数栈
 
	optr.push('#');      //置于符栈顶
    int len = strlen(s);
    bool is_minus = true;  // 判断是不是负号
 
    for (g_pos = 0; g_pos < len;)
    {
        //1. 负号
        if (s[g_pos] == '-' && is_minus)  // 是负号
        {
            opnd.push(0);
            optr.push('-');
            g_pos++;
        }
        //2. 是右括号 )
        else if (s[g_pos] == ')')
        {
            is_minus = false;
            g_pos++;
 
            while (optr.top() != '(' && optr.size() > 1)
            {
                double a2 = opnd.top();
                opnd.pop();
                double a1 = opnd.top();
                opnd.pop();
                char op = optr.top();
                optr.pop();
 
                double result = Operate(a1, op, a2);
                opnd.push(result);
            }
            optr.pop();  // 删除'('
            if (optr.size() < 1)
            {
            	cout << "ERROR IN INFIX NOTATION" << endl;
            	return 0;
			}
        }
        //3. 数字
        else if (s[g_pos] >= '0' && s[g_pos] <= '9')
        {
            is_minus = false;
            opnd.push(Translation(g_pos));
        }
        //4. ( 左括号
        else if (s[g_pos] == '(')
        {
            is_minus = true;
            optr.push(s[g_pos]);
            g_pos++;
        }
        //5. + - * / ^ % 
        else if (s[g_pos] == '+' || s[g_pos] == '-' || s[g_pos] == '*' || s[g_pos] == '/' || s[g_pos] == '^' || s[g_pos] == '%' )
        {
            while (GetLevel(s[g_pos]) <= GetLevel(optr.top()))    //当前优先级小于栈顶优先级
            {
                double a2 = opnd.top();
                opnd.pop();
                double a1 = opnd.top();
                opnd.pop();
                char op = optr.top();
                optr.pop();
 
                double result = Operate(a1, op, a2);
                opnd.push(result);
            }
 
            optr.push(s[g_pos]);
            g_pos++;
        }
        //6.输入字符不属于数字或规定运算符 
        else
        {
        	cout << "ERROR IN INFIX NOTATION" << endl;
        	return 0;
		}
    }
    
    //对剩余的运算符及操作数进行计算 
    while (optr.top() != '#' && opnd.size() >= 2)
    {
        double a2 = opnd.top();
        opnd.pop();
        double a1 = opnd.top();
	    opnd.pop();
	    char op = optr.top();
	    double result = Operate(a1, op, a2);
        opnd.push(result);
        optr.pop();
    }
    optr.pop();
    //计算结束并弹出#后运算符栈仍不为空,说明最后弹出的不为#,有多余运算符 
	if (!optr.empty())
    {
    	cout << "ERROR IN INFIX NOTATION" << endl;
    	return 0;
	}
	else if(opnd.size() != 1)
    {
    	cout << "ERROR IN INFIX NOTATION" << endl;
    	return 0;
	}
	else
	{
	    cout << setiosflags(ios::fixed) << setprecision(2) << opnd.top() << endl;
	    return 0;
	}
	

}
 
int main()
{
    cin >> s;
    Compute();
    return 0;
}

判断布尔矩阵的奇偶性

题目描述

布尔矩阵是指由0和1组成的矩阵,一个布尔矩阵有奇偶均势特性,当且仅当矩阵的每行、每列得总和为偶数,即包含偶数个1,该矩阵就具有奇偶均势特性。如下面这个4*4的矩阵就具有奇偶均势特性:

1 0 1 0

0 0 0 0

1 1 1 1

0 1 0 1

每一行的和分别为2,0,4,2,每一列的和分别为2,2,2,2。

编写程序,读入一个n*n阶矩阵并检查它是否具有奇偶均势特性。如果没有,你的程序应当再检查一下它是否可以通过修改一位(把0改为1,把1改为0)来使它具有奇偶均势特性。如果不可能,这个矩阵就被认为是破坏了。

输入:

第一行是一个整数n ( 0< n < 100 ),代表该矩阵的大小。然后输入n 行,每行n个整数(0或1),由空格分隔。

输出:

如果矩阵具有奇偶均势特性,输出“OK”;如果能通过只修改该矩阵中的一位来使它具有奇偶均势特性,则输出“Change bit (i,j)”,这里i和j是被修改的元素的行与列(行,列号从1开始);否则,输出“Corrupt”   

 

样例输入输出

样例1
输入:
4
1 0 1 0
0 0 0 0
1 1 1 1
0 1 0 1
输出:
OK
样例2
输入:
4
1 0 1 0
0 0 1 0
1 1 1 1
0 1 0 1
输出:
Change bit (2,3)
样例3
输入:
4
1 0 1 0
0 1 1 0
1 1 1 1
0 1 0 1
输出:
Corrupt

代码

#include<bits/stdc++.h>
using namespace std;

int main() {
	int n;
	cin >> n; 
	if (n <= 0 || n >= 100) {
		cout << "error";
		return -1;
	}
	
	vector<vector<int>> matrix(n, vector<int>(n));
	
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			cin >> matrix[i][j];
	
	int flag1 = 0, flag2 = 0; 
	
	int x = 0;
	for (int i = 0; i < n; ++i) {
		int rowSum = 0;
		for (int j = 0; j < n; ++j)
			rowSum += matrix[i][j];
		if (rowSum % 2 != 0) {
			flag1++;
			x = i;
		}
	}
	

	int y = 0;
	for (int j = 0; j < n; ++j) {
		int colSum = 0;
		for (int i = 0; i < n; ++i)
			colSum += matrix[i][j];
		if (colSum % 2 != 0) {
			flag2++;
			y = j;
		}
	}
	

	if (flag1 == 0 && flag2 == 0) {
		cout << "OK" << endl;
	} else if (flag1 == 1 && flag2 == 1) {
		cout << "Change bit (" << x + 1 << "," << y + 1 << ")" << endl;
	} else {
		cout << "Corrupt" << endl;
	}
	
	return 0;
}

求最大收益 

题目描述

已知某一只股票的每一日收盘价格,假设只可以进行一次先买后卖,求每股最大收益。

输入:

先输入包含的股票价格数量,然后输入股票价格(大于0的整数)。

输出:

最大收益。

如果是递减,最大收益为0。

 

样例输入输出

样例1

输入:

3
4 3 2

输出:

0

样例2

输入:

5
9 10 6 9 5

输出:

3

代码

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

int maxProfit(vector<int>& prices) {
    int n = prices.size();
    if (n <= 1)
        return 0; 

    int minPrice = prices[0]; 
    int maxProfit = 0;


    for (int i = 1; i < n; ++i) {
        maxProfit = max(maxProfit, prices[i] - minPrice); 
        minPrice = min(minPrice, prices[i]); 
    }

    return maxProfit; 
}

int main() {
    int n;
    cin >> n;

    if (n <= 0) {
        cerr << "Error";
        return 0;
    }

    vector<int> prices(n);
    for (int i = 0; i < n; ++i) {
        cin >> prices[i];
    }

    int max_profit = maxProfit(prices); 
    cout << max_profit; 

    return 0;
}

 三元组表示的稀疏矩阵的乘法运算

题目描述

对两个由三元组表示的稀疏矩阵进行乘法运算

输入:

第一行为三个整数row,column,count,用空格分隔,分别表示稀疏矩阵的行数、列数、非零元素的个数。

第二行开始输入该稀疏矩阵的三元组,每行三个整数,空格分隔,分别代表一个非零元素的行标、列标、值,共输入count行。

空一行后开始输入第二个稀疏矩阵的row,column,count,及三元组。

输出:

如果计算结果为零矩阵,输出“The answer is a Zero Matrix”,如果结果为非零矩阵,输出结果的三元组表示,要求输出三元组有序。如果无法计算矩阵乘法,输出“ERROR”。

 

样例输入输出

样例1

输入:

2 2 2
1 1 1
2 2 1

2 2 2
1 2 2
2 1 2

输出:

1 2 2
2 1 2

样例2

输入:

2 2 1
1 1 5

2 2 1
2 2 -5

输出:

The answer is a Zero Matrix

样例3

输入:

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

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

输出:

ERROR

代码

#include <bits/stdc++.h>
using namespace std;

struct Element {
	int row;
	int col;
	int value;
};

vector<Element> multiplySparseMatrices(const vector<Element>& mat1, const vector<Element>& mat2, int row1, int col1, int col2) {
	vector<Element> result;
	vector<vector<int>> intermediate(row1, vector<int>(col2, 0));
	
	for (const auto& elem1 : mat1) {
		for (const auto& elem2 : mat2) {
			if (elem1.col == elem2.row) {
				intermediate[elem1.row - 1][elem2.col - 1] += elem1.value * elem2.value;
			}
		}
	}
	
	for (int i = 0; i < row1; ++i) {
		for (int j = 0; j < col2; ++j) {
			if (intermediate[i][j] != 0) {
				result.push_back({i + 1, j + 1, intermediate[i][j]});
			}
		}
	}
	
	return result;
}

int main() {
	int row1, col1, count1;
	cin >> row1 >> col1 >> count1;
	
	vector<Element> mat1(count1);
	for (int i = 0; i < count1; ++i) {
		cin >> mat1[i].row >> mat1[i].col >> mat1[i].value;
	}
	
	int row2, col2, count2;
	cin >> row2 >> col2 >> count2;
	
	vector<Element> mat2(count2);
	for (int i = 0; i < count2; ++i) {
		cin >> mat2[i].row >> mat2[i].col >> mat2[i].value;
	}
	
	if (col1 != row2) {
		cout << "ERROR" << endl;
	} else {
		vector<Element> result = multiplySparseMatrices(mat1, mat2, row1, col1, col2);
		
		if (result.empty()) {
			cout << "The answer is a Zero Matrix" << endl;
		} else {
			sort(result.begin(), result.end(), [](const Element& a, const Element& b) {
				if (a.row == b.row) {
					return a.col < b.col;
				}
				return a.row < b.row;
			});

			for (const auto& elem : result) {
				cout << elem.row << " " << elem.col << " " << elem.value << endl;
			}
		}
	}
	
	return 0;
}

哈夫曼树A

题目描述

合并两个水晶碎块需要的能量是两个水晶碎块的能量和。假设只可以两两合并,请求出一堆水晶碎块合并成一整块水晶需要的最小能量。

题目输入:

第一行输入水晶碎块的个数n(1<=n<100),随后输入n个整数

题目输出:

合并最小能量(取值在long范围内)

提示:注意题目标题。

 

样例输入输出

样例1
输入:
6
8282
165
5
7431
9137
3
输出:
48694

代码

#include <bits/stdc++.h>
using namespace std;


long calculateMinimumCost(priority_queue<int, vector<int>, greater<int>>& q) {
	long sum = 0;
	while (q.size() >= 2) {
		int a = q.top(); // 取出最小的数值
		q.pop();
		int b = q.top(); // 取出次小的数值
		q.pop();
		int c = a + b; // 合并
		sum += c; 
		q.push(c); // 放回
	}
	return sum; 
}

int main() {
	int n;
	cin >> n;
	if(n<1 || n > 100) return 1;

	priority_queue<int, vector<int>, greater<int>> q; 
	for (int i = 0; i < n; ++i) {
		int m;
		cin >> m;
		q.push(m); 
	}
	long minCost = calculateMinimumCost(q); 
	cout << minCost << endl;
	return 0;
}

linux路径

题目描述

给定一个非最简的Linux文件绝对路径,将其简化为标准的Linux文件绝对路径。

在Linux文件路径中,一个英文句号 . 表示当前目录,两个连续的英文句号 .. 表示返回到上一级目录。

标准的Linux文件绝对路径具有以下特点

第一个字符为斜杠 /

两个目录名称直接有且仅有一个斜杠 /

除根目录外,路径结尾不能为斜杠 /

不会出现一个英文句号 . 或者两个连续的英文句号 ..

Input Format

输入由一行字符串组成,为非最简的Linux文件绝对路径。

Output Format

输出一行,为最简化的Linux文件绝对路径。

Example

Input

/aaa/../../bbb/ccc/..///./..

Output

/

说明

路径从根目录开始从左往右进行解析

aaa 表示进入根目录下 aaa 目录

.. 表示返回上一级目录,即返回根目录

.. 表示返回上一级目录,但当前目录为根目录,无上一级目录。故仍处于根目录。

bbb 表示进入根目录下 bbb 目录

ccc 表示进入 bbb 目录下 ccc 目录

.. 表示返回上一级目录,即返回 bbb 目录

后续若干个连续的斜杠 / 间没有目录名称,直接删除

. 表示当期文件夹,故仍处于 bbb 目录

.. 表示返回上一级目录,即返回根目录

根目录用斜杠 / 表示,故输出斜杠 /

 

样例输入输出

样例1
输入:
/aaa/../../bbb/ccc/..///./..
输出:
/
样例2
输入:
/home/
输出:
/home

代码

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

string simplifyPath(const string& path) {
    stack<string> dirs; 
    string dir; 
    size_t i = 0;

    while (i < path.size()) {
        while (i < path.size() && path[i] == '/') {
            i++;
        }
        dir.clear();
        while (i < path.size() && path[i] != '/') {
            dir.push_back(path[i]);
            i++;
        }

        if (dir == "..") {
            if (!dirs.empty()) {
                dirs.pop(); 
            }
        } else if (dir != "." && !dir.empty()) {
            dirs.push(dir); 
        }
    }

    string simplified_path;
    while (!dirs.empty()) {
        simplified_path = "/" + dirs.top() + simplified_path;
        dirs.pop();
    }

    return simplified_path.empty() ? "/" : simplified_path;
}

int main() {
    string path;
    while (getline(cin, path)) {
        string simplified_path = simplifyPath(path);
        cout << simplified_path << endl;
    }
    return 0;
}

有序线性表合并

题目描述

已知顺序存储的线性表,依次存放两个分别大小有序线性表,(a1...an)(b1....bm),即ai>=ai-1,bj>=bj-1(1<i<=n,1<j<=m)尝试设计算法合并成为一个非降序线性表。要求辅助存储空间复杂度为O(1)。试分析算法的时间复杂度。

输入:有序线性表长度n,m,n+m个分别有序的整数。

输出:非降序序列。

样例输入输出

样例1

输入:

3 5
1 5 8 3 4 7 9 11

输出:

1 3 4 5 7 8 9 11

 代码

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

void mergeNum(vector<int>& nums1, int m, vector<int>& nums2, int n) {
    int i = m - 1; 
    int j = n - 1; 
    int k = m + n - 1; 

    while (j >= 0) {
        nums1[k--] = nums2[j--];
    }
}

int main() {
    int n, m;
    cin >> n >> m;

    vector<int> nums1(n + m); 
    vector<int> nums2(m);
    for (int i = 0; i < n; ++i) {
        cin >> nums1[i];
    }
    for (int i = 0; i < m; ++i) {
        cin >> nums2[i];
    }

    mergeNum(nums1, n, nums2, m);

    for (int i = 0; i < n + m - 1; ++i) {
        for (int j = 0; j < n + m - i - 1; ++j) {
            if (nums1[j] > nums1[j + 1]) {
                swap(nums1[j], nums1[j + 1]);
            }
        }
    }

    for (int i = 0; i < n + m; ++i) {
        cout << nums1[i] << " ";
    }

    return 0;
}

基数排序

题目描述

根据输入,输出基数排序的每趟排序结果。

输入格式:输入数字为正整数,先输入排序数字个数,然后输入需要排序的数字序列。

输出格式:每趟排序结果。行尾无空格。

要求:程序需要实现排序,其他可以使用STL包。

 

样例输入输出

样例1

输入:

8
2343
6
66
152310
5594
592783
27
8

输出:

152310 2343 592783 5594 6 66 27 8
6 8 152310 27 2343 66 592783 5594
6 8 27 66 152310 2343 5594 592783
6 8 27 66 152310 2343 592783 5594
6 8 27 66 2343 5594 152310 592783
6 8 27 66 2343 5594 152310 592783

代码

#include <iostream>
using namespace std;

void initSize(int * radixsize){
    for(int i=0;i<10;i++){
        radixsize[i]=0;
    }
}

void div(int * data, int n){
    for(int i=0;i<n;i++){
    data[i]=data[i]/10;
    }
}

int getbit(int value, int k){
    for(int i = 0;i<k-1;i++){
        value = value/10;
    }
    return value % 10;
}

void output(int *data, int n){
    for(int i = 0;i<n-1;i++){
        cout<<data[i]<<" ";
    }
    cout<<data[n-1]<<endl;
}

int main() {
    int n;
    cin >> n;
    int *data = new int[n];

    for (int i = 0; i < n; i++) {
        cin >> data[i];
    }
    int * radix = new int[n*10];
    int * radixsize = new int[10];
    bool done = false;
    int curpos = 0;
while(!done){
    curpos++;
    initSize(radixsize);
    done = true;
    for(int i=0;i<n;i++){
        int v = getbit(data[i], curpos);
        if(v >0) {
            done = false;
        }
        radix[v + (radixsize[v]++*10)] =data[i];

    }
    if(done)  {
        break;
    }
    int datapos = 0;
    for(int j=0;j<10;j++){
        for(int k = 0; k < radixsize[j]; k++){
            data[datapos++] = radix[10 * k + j];
        }
    }
    output(data, n);
}
return 0;
}

创建RB树

题目描述

RB(红黑)树除了是一个二叉搜索树之外,还满足下面规则:

    1)每个结点要么是红的,要么是黑的。

    2)根结点是黑的。

    3)每个叶结点,即空结点是黑的。

    4)如果一个结点是红的,那么它的俩个儿子都是黑的。

    5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。

在给定插入序列的情况下,创建RB树,并输出最大值、最小值。

输入格式:

对于每种情况,第一行包含一个正整数N(<=20)。后边为N个不同的整数值,每个整数值以空格隔开。

第二行为要删除的节点个数M,后边为M个不同的整数值,以空格隔开。

输出格式:

第一行为RB树的前序遍历序列,以空格隔开,其中节点值后使用(B)和(R)表示节点的颜色;

第二行为RB树的最大值,最小值,以空格隔开;

第三行为删除M个节点之后的RB树的前序遍历序列,以空格隔开,若树为空,则输出Null;

注意:遍历输出最后一个结点有空格。删除带有双子结点时,找直接后继。

 

样例输入输出

样例1

输入:

13 1 45 34 98 9 4 35 23 36 37 90 85 80
3 85 27 9

输出:

34(B) 4(B) 1(B) 9(B) 23(R) 45(B) 36(B) 35(R) 37(R) 90(R) 85(B) 80(R) 98(B) 
1 98
34(B) 4(B) 1(B) 23(B) 45(B) 36(B) 35(R) 37(R) 90(R) 80(B) 98(B) 

样例2

输入:

3 18 2 7
0

输出:

7(B) 2(R) 18(R) 
2 18
7(B) 2(R) 18(R) 

 代码

//80分
#include<bits/stdc++.h>
using namespace std;

enum RBTColor{
    R,
    B
};
class TreeNode{
public:
    int data;
    RBTColor color;
    TreeNode* left, *right, *parent;
        TreeNode(int _data, RBTColor c, TreeNode* l, TreeNode* r, TreeNode* p):data(_data),color(c),left(l),right(r),parent(p){};

};

class RBTree{
private:
    TreeNode* root;
    //旋转
    void LeftRotate(TreeNode* node){
        TreeNode* rchild = node->right;
        node->right = rchild->left;
        if(rchild->left) rchild->left->parent = node;
        rchild->parent = node->parent;
        if(node->parent == nullptr) root = rchild;
        else if(node == node->parent->left) node->parent->left = rchild;
        else node->parent->right = rchild;
        rchild->left = node;
        node->parent = rchild;
    }

    void RightRotate(TreeNode* node){
        TreeNode* lchild = node->left;
        node->left = lchild->right;
        if (lchild->right) lchild->right->parent = node;
        lchild->parent = node->parent;
        if (node->parent == nullptr) root = lchild;
        else if (node == node->parent->left) node->parent->left = lchild;
        else node->parent->right = lchild;
        lchild->right = node;
        node->parent = lchild;
    }
    //插入与删除
    void InsertNode(TreeNode* node){
        if (root == nullptr) {
            root = node;
            return;
        }
        TreeNode* tmp = root, * ptmp = nullptr;
        while (tmp) {
            ptmp = tmp;
            if (node->data < tmp->data) tmp = tmp->left;
            else tmp = tmp->right;
        }
        node->parent = ptmp;
        if (node->data < ptmp->data) ptmp->left = node;
        else ptmp->right = node;
        node->color = R;
        InsertFix(node);        
    }

    void InsertFix(TreeNode* node){
        while (node->parent && node->parent->color == R) {
            if (node->parent == node->parent->parent->left) {
                TreeNode* uncle = node->parent->parent->right;
                if (uncle && uncle->color == R) {
                    node->parent->color = B;
                    uncle->color = B;
                    node->parent->parent->color = R;
                    node = node->parent->parent;
                }
                else {
                    if (node == node->parent->right) {
                        node = node->parent;
                        LeftRotate(node);
                    }
                    node->parent->color = B;
                    node->parent->parent->color = R;
                    RightRotate(node->parent->parent);
                }
            }
            else {
                TreeNode* uncle = node->parent->parent->left;
                if (uncle && uncle->color == R) {
                    node->parent->color = B;
                    uncle->color = B;
                    node->parent->parent->color = R;
                    node = node->parent->parent;
                }
                else {
                    if (node == node->parent->left) {
                        node = node->parent;
                        RightRotate(node);
                    }
                    node->parent->color = B;
                    node->parent->parent->color = R;
                    LeftRotate(node->parent->parent);
                }
            }
        }
        root->color = B;
    }

    void DeleteNode(TreeNode* node){
        RBTColor tcolor = B;
        TreeNode* child = nullptr;
        if (node->left == nullptr) child = node->right;
        else if (node->right == nullptr) child = node->left;
        else {
            TreeNode* tmp = node->right;
            while (tmp->left) tmp = tmp->left;
            child = tmp;
        }
        if (child) child->parent = node->parent;
        if (node->parent == nullptr) root = child;
        else if (node == node->parent->left) node->parent->left = child;
        else node->parent->right = child;
        if (node->color == B) {
            if (child && child->color == R) child->color = B;
            else DeleteFix(child, node->parent);
        }
        delete node;
    }

    void DeleteFix(TreeNode* node, TreeNode* parent){
        while (node != root && (node == nullptr || node->color == B)) {
            if (node == parent->left) {
                TreeNode* brother = parent->right;
                if (brother->color == R) {
                    brother->color = B;
                    parent->color = R;
                    LeftRotate(parent);
                    brother = parent->right;
                }
                if ((brother->left == nullptr || brother->left->color == B) && (brother->right == nullptr || brother->right->color == B)) {
                    brother->color = R;
                    node = parent;
                    parent = node->parent;
                }
                else {
                    if (brother->right == nullptr || brother->right->color == B) {
                        brother->left->color = B;
                        brother->color = R;
                        RightRotate(brother);
                        brother = parent->right;
                    }
                    brother->color = parent->color;
                    parent->color = B;
                    brother->right->color = B;
                    LeftRotate(parent);
                    node = root;
                    break;
                }
            }
            else {
                TreeNode* brother = parent->left;
                if (brother->color == R) {
                    brother->color = B;
                    parent->color = R;
                    RightRotate(parent);
                    brother = parent->left;
                }
                if ((brother->right == nullptr || brother->right->color == B) && (brother->left == nullptr || brother->left->color == B)) {
                    brother->color = R;
                    node = parent;
                    parent = node->parent;
                }
                else {
                    if (brother->left == nullptr || brother->left->color == B) {
                        brother->right->color = B;
                        brother->color = R;
                        LeftRotate(brother);
                        brother = parent->left;
                    }
                    brother->color = parent->color;
                    parent->color = B;
                    brother->left->color = B;
                    RightRotate(parent);
                    node = root;
                    break;
                }
            }
        }
        if (node) node->color = B;
    }
    //前序遍历
    void PreOrderNode(TreeNode* tree) const{
        if (tree == nullptr) return;
        cout << tree->data;
        if (tree->color == B) cout << "(B) ";
        else cout << "(R) ";
        PreOrderNode(tree->left);
        PreOrderNode(tree->right);
    }
public:
    RBTree(){root = nullptr;};
    ~RBTree() { }
    //插入
    void Insert(int _data){
        TreeNode* newNode = new TreeNode(_data, B, nullptr, nullptr, nullptr);
        InsertNode(newNode);
    }
    void Delete(int _data){
        TreeNode* tmp = root;
        while (tmp) {
            if (_data < tmp->data) tmp = tmp->left;
            else if (_data > tmp->data) tmp = tmp->right;
            else break;
        }
        if (tmp == nullptr) return;
        DeleteNode(tmp);
    }

    //前序遍历
    void PreOrder() const{
        if (root == nullptr) cout << "Null";
        else PreOrderNode(root);
        cout << endl;       
    }

    //查找最大最小值
    void FindMaxMin() const {
        TreeNode* tmp1 = root;
        TreeNode* tmp2 = root;
        while (tmp1->left) tmp1 = tmp1->left;
        while (tmp2->right) tmp2 = tmp2->right;
        cout << tmp1->data << ' ' << tmp2->data << endl;
    }

};

int main() {
    int n, m;

    cin >> n;
    RBTree t;
    for (int i = 0; i < n; i++) {
        int insertValue;
        cin >> insertValue;
        t.Insert(insertValue);
    }

    cin >> m;
    int* deleteValues = new int[m];
    for (int i = 0; i < m; i++) {
        cin >> deleteValues[i];
    }
    t.PreOrder();
    t.FindMaxMin();
    for (int i = 0; i < m; i++) {
        t.Delete(deleteValues[i]);
    }
    delete[] deleteValues;
    t.PreOrder();
    return 0;
}

约瑟夫环问题

题目描述

一个刚出锅的山芋,在围成一圈的n(以编号1,2,3...n分别表示 )个孩子间传递。大家一起数数,从编号为1的孩子开始报数,每数一次,当前拿着山芋的孩子就把山芋交给紧邻其右的孩子。 一旦数到事先约定的某个数k , 那个人就出列,他的下一个人又从1开始报数,数到数k的那个人就出列。如此反复,最后剩下的那个孩子就是幸运者。

试实现算法josephus(int n, int k),输出孩子们出列的次序

程序输入:n k

程序输出:孩子们出列的次序

 

样例输入输出

样例1

输入:

8 3

输出:

3->6->1->5->2->8->4->7

代码

#include<iostream>
#include<queue>
using namespace std;

int main()
{
	queue<int> res;
	int n, k;
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
	{
		res.push(i);
	}
	int cnt = 0;
	while (!res.empty())
	{
		for (int i = 1; i <= k - 1; i++)
		{
			res.push(res.front());
			res.pop();
		}

        if (res.front() == res.back()){
            cout << res.front();
        }
        else {
		cout << res.front() << "->";
        }
		res.pop();
	}
	return 0;
}

工程最短消耗

题目描述

给出一个工程中N个阶段的时间消耗和依赖关系,试求出工程的最短时间消耗。

Input Format

输入N 0<N<=20。

随后输入N行数据,每行包含从1起始的阶段编号S、时间消耗T、以及用分号隔开的所依赖的不同阶段编号【如果不依赖其他阶段则此项为空】

Output Format

输出一行,为完成N个阶段的时间消耗。如果依赖关系不为DAG则输出"error"

样例输入输出

样例1
输入:
4
1 3
2 4
3 5 1;2;
4 3 3;
输出:
12
样例2
输入:
4
1 3 3;
2 4
3 5 1;2;
4 3 3;
输出:
error

代码

#include <bits/stdc++.h>
using namespace std;

int checkDependency(int dependencyMatrix[20][20], int N) {
	queue<int> q;
	int* inDegree = new int[N];
	int* visited = new int[N];
	for (int i = 0; i < N; i++) {
		inDegree[i] = 0;
		visited[i] = 0;
	}

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (dependencyMatrix[i][j] != -1)
				inDegree[j]++;
		}
	}

	for (int i = 0; i < N; i++) {
		if (inDegree[i] == 0) {
			q.push(i);
			visited[i] = 1;
			break;
		}
	}

	while (!q.empty()) {
		int current = q.front();
		for (int i = 0; i < N; i++) {
			if (dependencyMatrix[current][i] != -1)
				inDegree[i]--;
		}
		for (int i = 0; i < N; i++) {
			if (inDegree[i] == 0 && visited[i] == 0) {
				q.push(i);
				visited[i] = 1;
			}
		}
		q.pop();
	}

	for (int i = 0; i < N; i++) {
		if (visited[i] == 0) return -1;
	}

	return 0;
}

int findMaxPath(int start, int dependencyMatrix[20][20], int N, int* timeCost) {
	int* endTime = new int[N];
	int* processed = new int[N];
	for (int i = 0; i < N; i++) {
		endTime[i] = 0;
		processed[i] = 0;
	}

	queue<int> q;
	q.push(start);
	while (!q.empty()) {
		int current = q.front();
		for (int i = 0; i < N; i++) {
			if (dependencyMatrix[current][i] != -1) {
				q.push(i);
				endTime[i] = max(endTime[i], endTime[current] + dependencyMatrix[current][i]);
				processed[current] = 1;
			}
		}
		q.pop();
	}

	for (int i = 0; i < N; i++) {
		endTime[i] += timeCost[i];
	}

	int maxTime = 0;
	for (int i = 0; i < N; i++) {
		if (processed[i] == 0 && endTime[i] > maxTime)
			maxTime = endTime[i];
	}

	return maxTime;
}

int main() {
	int N;
	string input;
	cin >> N;
	getchar();
	int dependencyMatrix[20][20];
	int* timeCost = new int[N];

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++)
			dependencyMatrix[i][j] = -1;
	}

	for (int i = 0; i < N; i++) {
		getline(cin, input);
		int k = 2;
		if (input[k] == ' ') k++;

		if ((k + 1 < input.length() && input[k + 1] == ' ') || k == input.length() - 1) {
			timeCost[i] = input[k] - '0';
			k += 2;

		}
		else {
			timeCost[i] = 10 * (input[k] - '0') + input[k + 1] - '0';
			k += 3;
		}

		while (k + 1 < input.length()) {
			if (input[k + 1] == ';') {
				dependencyMatrix[input[k] - '0' - 1][i] = input[k] - '0' - 1;
				k += 2;
			}
			else {
				dependencyMatrix[(input[k] - '0' - 1) * 10 + input[k + 1] - '0' - 1][i] = (input[k] - '0' - 1) * 10 + input[k + 1] - '0' - 1;
				k += 3;
			}
		}
	}

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (dependencyMatrix[i][j] != -1) dependencyMatrix[i][j] = timeCost[dependencyMatrix[i][j]];
		}
	}

	if (checkDependency(dependencyMatrix, N) == -1) {
		cout << "error" << endl;
		return 0;
	}
	else {
		int maxTime = 0;
		for (int i = 0; i < N; i++) {
			int flag = 0;
			for (int j = 0; j < N; j++) {
				if (dependencyMatrix[j][i] != -1) {
					flag = 1;
					break;
				}
			}
			if (flag == 0) {
				int currentMax = findMaxPath(i, dependencyMatrix, N, timeCost);
				if (currentMax > maxTime) 
					maxTime = currentMax;
			}
		}

		cout << maxTime << endl;
		return 0;
	}
}

判断是否为堆-堆整理

题目描述

请判断输入的整数序列是否为堆。

如果为最大堆,请输出“max ”以及整理后的最小堆,整数序列数字之间有空格,最后无空格。

如果为最小堆,请输出“min ” 以及整理后的最大堆,整数序列数字之间有空格,最后无空格。

如果不为堆,请输出整理后的最大堆,整数序列数字之间有空格,最后无空格。

如果既是最大堆也是最小堆,请只输出“max min ”

Input Format

先输入整数序列个数n 0<n<1000

然后输入n个整数序列,整数取值范围【-100000,100000】

Output Format

最大堆或最小堆序列

注意:序列最后无空格,max和min后面均有空格。

如案例,定义以下实现约束:两个相等子节点情况下,整理过程中,父节点下沉时,选择右沉。

10

10 8 1 7 2 -9 -6 -9 -8 -2

 两个相等子节点情况下,整理过程中,父节点下沉时,选择右沉。

 

样例输入输出

样例1

输入:

10
-9 -9 -6 -8 -2 1 10 7 8 2

输出:

min 10 8 1 7 2 -9 -6 -9 -8 -2

样例2

输入:

3
1 1 1

输出:

max min 

样例3

输入:

10
10 8 1 7 2 -9 -6 -9 -8 -2

输出:

max -9 -9 -6 -8 -2 1 10 7 8 2

样例4

输入:

10
-8 8 -9 10 -2 1 -6 -9 7 2 

输出:

10 8 1 7 2 -9 -6 -9 -8 -2

代码

#include<iostream>
using namespace std;

int flag = 0;
// 标记堆的类型:0表示未确定,1表示最大堆,2表示最小堆,3表示既是最大堆又是最小堆

// 是否为堆
void CheckHeap(int num[], int n) {
	bool isMax = true, isMin = true;
	int lChild, rChild;
	for (int i = 1; i <= n; ++i) {
		lChild = i * 2;
		rChild = i * 2 + 1;
		if (rChild <= n) {
		    // 结点与孩子相等,可以是最大堆也可以是最小堆
			if (num[i] == num[lChild] && num[i] == num[rChild])
			continue;
			// 结点的左右孩子都不比它小,不是最大堆
			else if (num[i] <= num[lChild] && num[i] <= num[rChild]) isMax = false;
			// 结点的左右孩子都不比它大,不是最小堆			
			else if (num[i] >= num[lChild] && num[i] >= num[rChild]) isMin = false;
			else {
				isMax = isMin = false;
				break;
			}
		}
		else if (lChild <= n) {
		    // 只有左孩子
			if (num[i] == num[lChild]) continue;
			else if (num[i] < num[lChild]) isMax = false;
			else if (num[i] > num[lChild]) isMin = false;
			else {
				isMax = isMin = false;
				break;
			}
		}
	}
	if (isMax == true) {
		if (isMin == false) flag = 1;
		if (isMin == true) flag = 3;
	}
	else {
		if (isMin == true) flag = 2;
		if (isMin == false) flag = 4;
	}
}

void BuildMaxHeap(int num[], int n) {
	for (int i = n / 2; i >= 1; --i) {
		int temp = num[i];
		int child = i * 2;
		while (child <= n) {
			if (child < n && num[child] <= num[child + 1]) child++;
			if (temp < num[child]) {
				num[child / 2] = num[child];
				child *= 2;
			}
			else break;
		}
		num[child / 2] = temp;
	}
}

void BuildMinHeap(int num[], int n) {
	for (int i = n / 2; i >= 1; --i) {
		int temp = num[i];
		int child = i * 2;
		while (child <= n) {
			if (child < n && num[child] >= num[child + 1]) child++;
			if (temp > num[child]) {
				num[child / 2] = num[child];
				child *= 2;
			}
			else break;
		}
		num[child / 2] = temp;
	}
}

void SortHeap(int num[], int n) {
	if (flag == 1) {
		cout << "max ";
		BuildMinHeap(num, n);
	}
	if (flag == 2) {
		cout << "min ";
		BuildMaxHeap(num, n);
	}
	if (flag == 3) {
		cout << "max min" << endl;
		return;
	}
	if (flag == 4) {
		BuildMaxHeap(num, n);
	}
	for (int i = 1; i <= n; ++i) {
		if (i == n) cout << num[i];
		else cout << num[i] << " ";
	}
}

int main() {
	int n, nums[1000];
	cin >> n;
	if(n<=0||n>=1000) return 1;
	for (int i = 1; i <= n; ++i){
		cin >> nums[i];
		if(nums[i]<-100000 || nums[i]>100000){
			cout << "error";
			return 1;
		}
	}

	
	CheckHeap(nums, n);
	SortHeap(nums, n);
	return 0;
}

判断排序方法

题目描述

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成N个只包含1个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下1个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数N (<=100);随后一行给出原始序列的N个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行末不得有多余空格。

 

样例输入输出

样例1

输入:

10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

输出:

Insertion Sort
1 2 3 5 7 8 9 4 6 0

样例2

输入:

10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

输出:

Merge Sort
1 2 3 8 4 5 7 9 0 6

代码

xxx 

旋转的矩阵

题目描述

给定一个n*m的矩阵,请以顺、逆时针交替旋转的方式打印出每个元素。

  

Input Format

第一行n m; 0<n,m<100

后n行,每行m个整数。

Output Format

n*m个矩阵元素,空格隔开。

Example

Input

3 4

1  2  3  4

10 11 12  5

9  8  7  6  

Output

1 2 3 4 5 6 7 8 9 10 11 12

样例输入输出

样例1
输入:
1 3
3 4 1
输出:
3 4 1
样例2
输入:
4 4
1  2  3  4
12 13 16  5
11 14 15  6
10  9  8  7
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
样例3
输入:
3 1
6
5
7
输出:
6 5 7

代码

#include<bits/stdc++.h>
using namespace std;


vector<int> rotateMatrix(vector<vector<int>> &matrix ){
       vector<int> result;
        if(matrix.empty()) return result;

        int top = 0;
        int bottom  = matrix.size()-1;
        int left = 0;
        int right = matrix[0].size()-1;

        while(true){
            if(top%2 == 0){
                for(int i = left; i<=right;++i) 
                    result.push_back(matrix[top][i]);
                if(++top > bottom) break;
                for(int i = top; i<=bottom;++i)
                    result.push_back(matrix[i][right]);
                if(--right < left) break;
                for(int i = right; i>=left; --i)
                    result.push_back(matrix[bottom][i]);
                if(--bottom < top) break;
                for(int i = bottom;i>=top; --i)
                    result.push_back(matrix[i][left]);
                if(++left>right) break;
            }

            else{
                for(int i = top; i<=bottom;++i)
                    result.push_back(matrix[i][left]);
                if(++left>right) break;
                for(int i = left; i<=right;++i) 
                    result.push_back(matrix[bottom][i]);
                if(--bottom >top) break;    
                for(int i = bottom;i>=top; --i)
                    result.push_back(matrix[i][right]);
                if(--right>left) break;    
                for(int i = right; i>=left; --i)
                    result.push_back(matrix[top][i]);
                if(++top >bottom) break;                                       

            }
        }
        return result;
}
int main(){
    int n, m;
    cin >> n >> m;
    vector<vector<int>> matrix(n,vector<int>(m ,0));
    
    for(int i = 0; i<n;++i){
        for(int j = 0; j<m;++j){
            cin >> matrix[i][j];
        }
    }
    vector<int> result = rotateMatrix(matrix);
    for(auto i:result){cout << i << " ";}
    return 0;

}

字符串应用-实现KMP匹配算法

题目描述

给定一个主串S和子串P,使用KMP算法查找子串P在主串S中存在的位置,若子串P在主串S中存在,则输出与子串P中第一字符相等的字符在主串S中的序号;若不存在则输出“no”

程序输入格式:主串S 子串P;

程序输出格式:输出与子串P中第一字符相等的字符在主串S中的序号;

输入样例:ababcabcacbab abcac

输出样例:5

 

样例输入输出

样例1

输入:

ababcabcacbab abcac

输出:

5

样例2

输入:

ABCDABCDABDE DBAEA

输出:

no

代码

#include <bits/stdc++.h>
using namespace std;
// 计算 next 数组
vector<int> computeNext(const string& pattern) {
	int m = pattern.length();
	vector<int> next(m);
	next[0] = -1;
	int k = -1;
	for (int i = 1; i < m; ++i) {
		while (k >= 0 && pattern[k + 1] != pattern[i])
			k = next[k];
		if (pattern[k + 1] == pattern[i])
			++k;
		next[i] = k;
	}
	return next;
}

// KMP 算法
int KMP(const string& text, const string& pattern) {
	int n = text.length();
	int m = pattern.length();
	vector<int> next = computeNext(pattern);
	int j = -1;
	for (int i = 0; i < n; ++i) {
		while (j >= 0 && pattern[j + 1] != text[i])
			j = next[j];
		if (pattern[j + 1] == text[i])
			++j;
		if (j == m - 1)
			return i - m + 1;
	}
	return -1;
}

int main() {
	string text, pattern;
	cin >> text >> pattern;
	int result = KMP(text, pattern);
	if (result != -1)
		cout << result << endl;
	else
		cout << "no" << endl;
	return 0;
}

互斥字符串

题目描述

给定一个仅含有英文大小写字母的字符串序列 s,若其中任意两个相邻字符都不是同一个字母的大小写形式,则称其为互斥字符串

程序需要将给定的字符串转换为互斥字符串。aa为互斥,aA和Aa为非互斥。

程序的每次操作可以从字符串中选出满足上述条件的两个相邻字符并删除,直到字符串整理好为止。

注:若最终结果为空字符串,请输出 -1。

要求时间复杂度O(n)

Input Format

输入由一行字符串组成。测试样例保证答案唯一。

Output Format

输出一行,为输入字符串经过若干次删除操作得到的互斥字符串。

说明

该样例存在多种转换路径,但最终输出相同

"abBAcCc" --> "aAcCc" --> "cCc" --> "c"

"abBAcCc" --> "abBAc" --> "aAc" --> "c"

样例输入输出

样例1
输入:
abBAcCc
输出:
c
样例2
输入:
AaBbCcDd
输出:
-1

代码

#include <iostream>
#include <string>
#include <stack>
using namespace std;
bool isCap(char c1, char c2){
     return abs(c1-c2) == 32;
}
int main() {
    string input;
    cin >> input;
    char* cstack = new char[input.length()];
    int top = -1;
    int pos = 0;

    while (pos < input.length()) {
        if (top == -1 || !isCap(cstack[top], input.at(pos))) {
        cstack[++top] = input.at(pos);
        }
        else{
            top--;

        }
        pos++;
    }
    if (top == -1) {
        cout << top;
        return 0;
    }
    else {
        cstack[++top] = '\0';
        cout << cstack;
        return 0;
    }
}

二叉树遍历及二叉树高度

题目描述

给出一棵二叉树的先序遍历和中序遍历序列,计算该二叉树的高度。其中,二叉树的先序和中序遍历序列为不包含重复英文字母(区别大小写)的字符串。

Input Format

二叉树结点的总个数n<=50

然后输入先序和中序遍历序列,两个序列长度均为n。  

Output Format

二叉树高度(整数) ,叶子结点高度为1 

样例输入输出

样例1

输入:

9
ABDGHCEIF
GDHBAEICF

输出:

4

代码

#include <bits/stdc++.h>
using namespace std;

struct TreeNode {
	char val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(char x) : val(x), left(nullptr), right(nullptr) {}
};


TreeNode* buildTree(const string& preorder, const string& inorder) {
	if (preorder.empty() || inorder.empty() || preorder.size() != inorder.size()) {
		return nullptr; // 处理边界情况,输入为空或者先序和中序序列长度不匹配
	}
	char rootValue = preorder[0]; // 根节点值为先序序列的第一个字符
	auto rootIndex = inorder.find(rootValue); // 找到根节点在中序序列中的位置
	if (rootIndex == string::npos) {
		return nullptr; // 处理错误情况,根节点不在中序序列中
	}
	TreeNode* root = new TreeNode(rootValue); // 创建根节点
	// 递归构建左子树和右子树
	root->left = buildTree(preorder.substr(1, rootIndex), inorder.substr(0, rootIndex));
	root->right = buildTree(preorder.substr(rootIndex + 1), inorder.substr(rootIndex + 1));
	return root;
}


int getHeight(TreeNode* root) {
	if (root == nullptr) {
		return 0; // 处理边界情况,空树的高度为0
	}
	int leftHeight = getHeight(root->left); // 左子树的高度
	int rightHeight = getHeight(root->right); // 右子树的高度
	return max(leftHeight, rightHeight) + 1; // 返回左右子树中较大的高度加1
}

int main() {
	int n;
	cin >> n;
	
	string preorder, inorder;
	cin >> preorder >> inorder;
	
	TreeNode* root = buildTree(preorder, inorder); 
	
	int height = getHeight(root); 
	cout << height << endl;
	
	delete root; 
	return 0;
}

多源最短路径

题目描述

一个有向图中有  个顶点和  条单向路径 , 试求任意两地点间最短距离。

Input Format

第一行两个正整数  和 ,分别代表点的数量和路径的数量。   0< <20, 0<=  <50

之后  行每行有三个整数  分别表示 路径 的起点和终点序号和路径长度。顶点编号从0开始,0<=i,j<n,0<k

Output Format

顶点之间最短路径矩阵(n*n),-1代表不连通。

每一行的最后一个数字后面没有空格。

样例输入输出

样例1

输入:

3 5
0 1 6
0 2 13
1 0 10
1 2 4
2 0 5

输出:

0 6 10
9 0 4
5 11 0

样例2

输入:

6 0

输出:

0 -1 -1 -1 -1 -1
-1 0 -1 -1 -1 -1
-1 -1 0 -1 -1 -1
-1 -1 -1 0 -1 -1
-1 -1 -1 -1 0 -1
-1 -1 -1 -1 -1 0

代码

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;

void floyd(vector<vector<int>>& graph, int n) {
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (graph[i][k] != INF && graph[k][j] != INF) {
                    graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]);
                }
            }
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;

    vector<vector<int>> graph(n, vector<int>(n, INF));

    for (int i = 0; i < n; ++i) {
        graph[i][i] = 0; 
    }

    for (int i = 0; i < m; ++i) {
        int u, v, w;
        cin >> u >> v >> w;
        graph[u][v] = w;
    }

    floyd(graph, n);

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (graph[i][j] == INF) {
                cout << "-1";
            } else {
                cout << graph[i][j];
            }
            if (j != n - 1) {
                cout << " ";
            }
        }
        cout << endl;
    }

    return 0;
}

完全二叉树的先序遍历

题目描述

给出一棵完全二叉树的先序遍历,输出其后序遍历。结点均为不重复的单个英文字母,区分大小写。结点总数小于52。

Input Format

输入先序字符串

Output Format

后序遍历字符串

 

样例输入输出

样例1

输入:

ABDGHCEIF

输出:

GHDCBIFEA

样例2

输入:

a

输出:

a

代码

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

class TreeNode {
public:
	TreeNode* leftChild;
	TreeNode* rightChild;
	char value;
	TreeNode(char v = NULL, TreeNode* l = NULL, TreeNode* r = NULL) : value(v), leftChild(l), rightChild(r) {}
};

// 后序遍历二叉树
void postorder(TreeNode* root) {
	if (root == nullptr) {
		return;
	}
	postorder(root->leftChild);
	postorder(root->rightChild);
	cout << root->value;
}

int main() {
	string preorder;
	cin >> preorder;
	
	// 检查输入是否为空
	if (preorder.empty()) {
		cout << "error" << endl;
		return 0;
	}
	
	TreeNode* tree = new TreeNode[preorder.size() + 1]; // 数组下标从1开始
	int n = 1;
	int m = 1;
	// 求s为满二叉树时的元素个数m
	while ((int)preorder.size() > m) {
		double u = (double)n;
		m += pow(2, u);
		n++;
	}
	
	// 构建完全二叉树
	for (int q = 1; q <= preorder.size(); q++) {
		if (2 * q <= (int)preorder.size()) tree[q].leftChild = &tree[2 * q];
		if (2 * q + 1 <= (int)preorder.size()) tree[q].rightChild = &tree[2 * q + 1];
	}
	
	tree[1].value = preorder[0];
	for (int i = 1, j = 1; i < (int)preorder.size();) {
		while (tree[j].value != NULL && tree[j].leftChild != NULL && i < (int)preorder.size()) {
			j = 2 * j;
			tree[j].value = preorder[i++];
		}
		if (tree[j / 2].rightChild != NULL && tree[j / 2].rightChild->value == NULL) {
			j = j + 1;
			tree[j].value = preorder[i++];
		}
		else if (tree[j / 2].rightChild != NULL && tree[j / 2].rightChild->value != NULL) {
			j = j / 2;
			while (j > 1 && tree[j / 2].rightChild != NULL && tree[j / 2].rightChild->value != NULL) j = j / 2;
			j = j + 1;
			tree[j].value = preorder[i++];
		}
		else if (tree[j / 2].rightChild == NULL) {
			j = j / 2 ;
			while (j > 1 && tree[j / 2].rightChild != NULL && tree[j / 2].rightChild->value != NULL) j = j / 2;
			j = j + 1;
			tree[j].value = preorder[i++];
		}
	}
	postorder(&tree[1]);
	delete[] tree;
	return 0;
}

创建AVL树并判断是否为完全二叉树

题目描述

在AVL树中,任何节点的两个子树的高度最多相差1;如果它们高度相差不止1,则需要重新平衡以恢复这种属性。

现在给定一个插入序列, 一个一个地将键值插入初始为空的AVL树中,输出得到的AVL树的层次顺序遍历序列,并判断它是否是一个完全二叉树。

输入格式:

第一行包含一个正整数N(<= 20)。然后在下一行给出N个不同的整数键。所有数字都用空格隔开。

输出格式:

第一行打印得到的AVL树的层次顺序遍历序列。所有数字都必须用空格隔开,并且行尾必须没有多余的空格。然后在下一行中,如果树为完全二叉树,则打印“Yes”;如果不是,则打印“No”。

样例输入输出

样例1

输入:

5
88 70 61 63 65

输出:

70 63 88 61 65
Yes

样例2

输入:

10
62 88 58 47 35 73 51 99 37 93

输出:

62 47 88 35 58 73 99 37 51 93
No

代码

#include <queue>
#include <vector>
#include <iostream>
using namespace std;
typedef struct AVLNode
{
	struct AVLNode *left,*right;
	int val,height;
}*Node;
int getHeight(Node root)
{
	if(root == NULL)	return 0;
	else	return root->height;
}
Node rightrotate(Node root)
{
	Node tmp = root->left;
	root->left = tmp->right;
	tmp->right = root;
	root->height = max(getHeight(root->left),getHeight(root->right)) + 1;
	tmp->height = max(getHeight(tmp->left),getHeight(tmp->right)) + 1;
	return tmp;
}
Node leftrotate(Node root)
{
	Node tmp = root->right;
	root->right = tmp->left;
	tmp->left = root;
	root->height = max(getHeight(root->left),getHeight(root->right)) + 1;
	tmp->height = max(getHeight(tmp->left),getHeight(tmp->right)) + 1;
	return tmp;
}
Node rightleftrotate(Node root)
{
	root->right = rightrotate(root->right);
	return leftrotate(root);
}
Node leftrightrotate(Node root)
{
	root->left = leftrotate(root->left);
	return rightrotate(root);
}
Node insert(Node root,int key)
{
	if(root == NULL)
	{
		root = new AVLNode();
		root->val = key;
		root->left = root->right = NULL;
		root->height = 1;
		return root;
	}
	else
	{
		if(key < root->val)
		{
			root->left = insert(root->left, key);
			if(getHeight(root->left) - getHeight(root->right) == 2)
			{
				if(key < root->left->val)	root = rightrotate(root);
				else root = leftrightrotate(root);
			}
		}
		else if(key > root->val)
		{
			root->right = insert(root->right, key);
			if(getHeight(root->right) - getHeight(root->left) == 2)
			{
				if(key > root->right->val)	root = leftrotate(root);
				else root = rightleftrotate(root);
			}
		}
	}
	root->height = max(getHeight(root->left),getHeight(root->right)) + 1;
	return root;
}
void level_order_traverse(Node root)
{
	queue<Node>q;
	vector<int>ans;
	q.push(root);
	bool flag = false,flag2 = false;
	while(!q.empty())
	{
		Node p = q.front();	
		q.pop();
		ans.push_back(p->val);
		if(p->left != NULL)
		{
			q.push(p->left);
			if(flag)	flag2 = true;
		}
		else	flag = true;
 
		if(p->right != NULL)
		{
			q.push(p->right);
			if(flag)	flag2 = true;
		}
		else flag = true;
	}
	for(int i = 0; i < ans.size(); i++)
	{
		if(i == ans.size() - 1)	cout << ans[i] << endl;
		else	cout << ans[i] << ' ';
	}
	if(!flag2)	cout << "Yes" << endl;
	else cout << "No" << endl;
}
int main()
{
	int n;
    cin >> n;
	Node root = NULL;
	for(int i = 1; i <= n; i++)
	{
		int x;
		cin >> x;
		root = insert(root, x);
	}
	level_order_traverse(root);
 
	return 0;
}

二元一次多项式求幂

题目描述

给定一个常数项为0的二元一次多项式,求该多项式的幂。

设未知数为x,y,输入为x和y的整数系数a,b以及整数幂n,输出形如以下样式

求幂运算的结果,按照x的幂降序排列

Input Format

输入未知数整数系数 a,b (-100<a,b<100),n (1<n<6)

Output Format

幂运算的结果的多项式,按照x幂降序排列  

说明

幂为1时不输出^1

系数为1时不输出系数,-1只输出负号。

样例输入输出

样例1
输入:
2 3 2
输出:
4x^2+12xy+9y^2

 代码

xxx

Dijkstra单源最短路径

题目描述

一个有向图中有  个顶点和  条单向路径 , 请使用Dijkstra算法,求出某一个顶点到其他顶点的最短路径。

Input Format

第一行两个正整数  和 ,分别代表点的数量和路径的数量。   1< <20, 0<=  <50

之后  行每行有三个整数  分别表示 路径 的起点、终点序号和路径长度。顶点编号从1开始,0<i,j<=n,0<k<100

源点编号p ,0<p<=n

Output Format

Ⅰ.Dijkstra计算过程;

Ⅱ.输出给定点v到其他各点的路径,以及最短距离。

注意输出格式

按照Dijkstra算法获取最短路径顺序进行输出,如果没有路径则输出“No Path to ”【顶点编号,升序排列,中间使用空格隔开】

样例输入输出

样例1
输入:
8 10
1 6 10
1 5 5
6 3 1
6 5 2
3 4 4
4 1 7
4 3 6
5 6 3
5 3 9
5 4 2
1
输出:
No.1 : 1 -> 5 , d = 5
No.2 : 1 -> 5 -> 4 , d = 7
No.3 : 1 -> 5 -> 6 , d = 8
No.4 : 1 -> 5 -> 6 -> 3 , d = 9
No.5 : No Path to 2 7 8

代码

#include<iostream>
#include<stack>

using namespace std;

struct edge
{
	int bg, ed, val;
	edge(int p = 0,int q = 0,int v = -1):bg(p), ed(q), val(v){}
};

struct Node
{
	int flag;//标示结点是否已被访问。 
	Node(int f = 0):flag(f){}
};
//存储距离该结点最近的点以及路径长 
struct path
{
	int length, k;
	path(int l = 101,int kk = 0):length(l),k(kk){}
	path(const path& p)
	{
		length = p.length;
		k = p.k;
	}
};
//得到距离该点最近的点的路径长度 
int minpath(int bg, int ed, edge* e, int m)
{
	if(bg == ed)return 0;
	int min = 101;
	for(int i = 0;i < m; i++)
		if(e[i].bg == bg && e[i].ed == ed && e[i].val < min)
			min = e[i].val;

		return min;
}

int main()
{
	int n, m, t1, t2, t3, s;
	cin >> n >> m;
	edge* e = new edge[m];
	Node* N = new Node[n];
	int* pre = new int[n];//与当前结点相连的前一个点。 
	path* p = new path[n];
    
   
	for(int i = 0; i < n; i++)
		p[i].k = i;

	for(int i = 0; i < n; i++)
		pre[i] = -1;

	for(int i = 0; i < m; i++)
	{
		cin >> t1 >> t2 >> t3;
		e[i].bg = t1 - 1;
		e[i].ed = t2 - 1;
		e[i].val = t3;
	}
	cin >> s;
	s -= 1;
	pre[s] = s;
	p[s].length = 0;
	N[s].flag = 1;

	int* key = new int[n];
	for(int i = 0; i < n; i++)
	{
		p[i].length = minpath(s, i, e, m);
		key[i] = p[i].length;//暂存各结点的最短路径。 
	}

	int c1, c2;
	c1 = s;//从源点开始搜寻。 
	for(int i = 0; i < n - 1; i++)
	{
		for(int j = 0; j < n; j++)
		{
			if(N[j].flag == 1)continue;//已访问,直接跳到下一个结点。 
			if(key[j] > (key[c1] + minpath(c1, j, e, m)))
				{
					key[j] = key[c1] + minpath(c1, j, e, m);
					pre[j] = c1;
				}
		}
		int min = 101, j = 0;;
		for(;j < n; j++)
		{
			if(N[j].flag == 1)continue;
			if(key[j] <= min)
				{
					min = key[j];
					c2 = j;
				}
		}
		
		N[c2].flag = 1;
		if(i == 0)pre[c2] = c1;
		p[c2].length = key[c2];
		c1 = c2;
	}

	for(int i = 0; i < n; i++)
		for(int j = i + 1; j < n; j++)
			if(p[j].length < p[i].length)
			{
				path pp = p[j];
				p[j] = p[i];
				p[i]= pp;
			}

	int count = 1, flag = 0;
	for(int i = 0; i < n; i++)
	{
		int num = p[i].k;
		if(p[i].k == s)continue;
		if(p[i].length == 101)
		{
			flag++;
			continue;
		}

		stack<int> st;
		st.push(num);
		while(pre[num] != s)
		{
			st.push(pre[num]);
			num = pre[num];
		}

		cout << "No." << count++ << " : " << s + 1 << " ";
		while(!st.empty())
		{
			cout << "-> " << st.top() + 1 << " ";
			st.pop();
		}
		cout << ", d = " << p[i].length << endl;
	}

	if(flag > 0)
	{
	cout << "No." << count << " : No Path to";
	int *np = new int[flag];
	int q = 0;
	for(int i = 0; i < n; i++)
	{
		if(p[i].length == 101) np[q++] = p[i].k + 1;
	}

	for(int i = 0;i < flag; i++)
		for(int j = i + 1; j < flag; j++)
			if(np[j] < np[i])
			{
				int tmp = np[j];
				np[j] = np[i];
				np[i] = tmp;
			}

	for(int i = 0; i < flag; i++)cout << " " << np[i];
	}

	return 0;

}

上机模拟(2024)

最大乘积

题目描述

对一个整型数组nums,在数组中找出由三个数组成的最大乘积,并输出这个乘积。

乘积在long表达范围内

输入样式:

先输入整数个数n

再依次输入n个整数

输出样式:

输出乘积

 

样例输入输出

样例2

输入:

4
-1 -2 -3 -4

输出:

-6

样例3

输入:

6
-5 -6 1 2 3 4

输出:

120

样例1

输入:

3
1 2 3

输出:

6

 代码

#include <bits/stdc++.h>
using namespace std;

long maximumProduct(vector<int> &nums) {
    sort(nums.begin(), nums.end());
    int n = nums.size();
    return max(nums[0] * nums[1] * nums[n - 1], nums[n - 3] * nums[n - 2] * nums[n - 1]);
}

int main() {
    int n;
    cin >> n;
    if(n<3) return 1;
    
    vector<int> nums(n);
    for(int i = 0; i < n; i++)
        cin >> nums[i];
    cout << maximumProduct(nums) << endl;
    return 0;
}

A(1)666

题目描述

给定1个正整数 x (int 范围内) ,如果 x 与其倒序获得的整数相加后可以获得一个与x位数相等且所有位数均为同一个数字的整数(例如666),输出 true ;否则,输出 false 

输入:

一个正整数

输出:

true or false

 

样例输入输出

样例1

输入:

234

输出:

true

样例2

输入:

10

输出:

true

样例3

输入:

29

输出:

false

代码

//90分
#include <bits/stdc++.h>
using namespace std;

bool isSame(int num){
    string s = to_string(num);
    char first = s[0];
    for(char c:s){
        if(c!=first)
            return false;
    }
    return true;
}

int reverseNumber(int num){
    int reversedNum = 0;
    while(num>0){
        reversedNum = reversedNum*10 + num%10;
        num/=10;
    }
    return reversedNum;
}
bool check(int num){
    int reversedNum = reverseNumber(num);
    int sum = reversedNum+num;
    return isSame(sum);
}
int main() {
    int num;
    cin>>num;
    if(check(num)) cout << "true" << endl;
    else cout << "false" << endl;
    return 0;
}

最少换乘中最短的路径

题目描述

给定一个无向图,n 个顶点编号为 0 到 n-1 , e条边,包含两个顶点和一个权重,请求从一个顶点到另外一个顶点最少换乘前提下的最短路径长度,并输出该路径长度。

输入格式:

先输入顶点和边的个数,n,e

再输入 e条带权重的边 ,输入样式为 v1 v2 cost ,即2个顶点编号和一个路径长度,其中cost为正整数。

最后输入两个顶点编号,start,end,

输出:

顶点 start到顶点end的最少换乘前提下的最短路径长度


例如图:

输入为

5 6
0 1 2
0 3 3
1 2 5
1 3 4
2 3 10
3 4 7
0 2

正确输出为:7

测试案例保证可达。

tips:

1.最少换乘可以借助宽度优先遍历实现

2.在最少换乘的基础上,只需要保证当前顶点的路径最短即可。即设vi已有最小换乘次数ri,最短路径disi,那么vi可达的顶点 可以根据ri,disi更新其最小换乘次数和最短路径(在能减少换乘并且缩短距离的情况下)

 

样例输入输出

样例1
输入:
5  6 
0  1  2
0  3  3
1  2  5
1  3  4
2  3  10
3  4  7
0  2
输出:
7

代码

#include <bits/stdc++.h>
using namespace std;

struct Edge {
    int to, cost;
};

// 定义节点结构体,用于优先级队列,包含当前顶点,换乘次数,以及从起点到当前顶点的距离
struct Node {
    int vertex, changes, distance;
    
    // 定义比较运算符,使优先级队列按换乘次数优先,其次按距离排序
    bool operator>(const Node& other) const {
        return changes > other.changes || (changes == other.changes && distance > other.distance);
    }
};

// 添加无向边到图中
void addEdge(vector<vector<Edge>>& graph, int u, int v, int cost) {
    graph[u].push_back({v, cost});
    graph[v].push_back({u, cost});
}

// 寻找最少换乘前提下的最短路径长度
int findShortestPathWithMinTransfers(int n, const vector<vector<Edge>>& graph, int start, int end) {
    // 初始化最小距离和最小换乘次数的矩阵
    vector<vector<int>> minDistance(n, vector<int>(n, INT_MAX));
    vector<int> minChanges(n, INT_MAX);
    // 优先级队列,用于Dijkstra算法
    priority_queue<Node, vector<Node>, greater<Node>> pq;

    // 将起点放入优先级队列
    pq.push({start, 0, 0});
    minChanges[start] = 0;
    minDistance[start][0] = 0;

    while (!pq.empty()) {
        // 取出队列中换乘次数最少且距离最短的节点
        auto [current, changes, distance] = pq.top();
        pq.pop();

        // 如果当前顶点是终点,返回其距离
        if (current == end) return distance;

        // 遍历当前顶点的所有邻居
        for (const auto& edge : graph[current]) {
            int next = edge.to;
            int nextDistance = distance + edge.cost;
            int nextChanges = changes + 1;

            // 如果找到更少换乘次数的路径,或者相同换乘次数下更短的路径,更新并加入队列
            if (nextChanges < minChanges[next] || (nextChanges == minChanges[next] && nextDistance < minDistance[next][nextChanges])) {
                minChanges[next] = nextChanges;
                minDistance[next][nextChanges] = nextDistance;
                pq.push({next, nextChanges, nextDistance});
            }
        }
    }

    return -1; // 如果没有找到路径,返回-1,但在本问题中保证路径存在
}

int main() {
    int n, e;
    cin >> n >> e;

    // 初始化图的邻接表表示法
    vector<vector<Edge>> graph(n);

    for (int i = 0; i < e; ++i) {
        int u, v, cost;
        cin >> u >> v >> cost;
        addEdge(graph, u, v, cost);
    }

    int start, end;
    cin >> start >> end;

    // 调用寻找路径函数并输出结果
    int result = findShortestPathWithMinTransfers(n, graph, start, end);
    cout << result << endl;

    return 0;
}

上机真题(2024)

统计范围内的元音字符串数

给你一个下标从0开始的字符串数组words和两个整数:left和right。如果字符串以元音字母开头并以元音字母结尾,那么该字符串就是一个元音字符串,其中元音字母是'a'、'e'、'i'、'o'、'u'。请返回左闭右开区间[left,right)内所有元音字符串的数目。其中1 <= words.length <= 1000,1 <= words[i].length <= 10,words[i]仅由小写英文字母组成,0 <= left <= right < words.length

    输入格式:第一个输入是一个整数n,表示字符串数组的长度。接下来是n个字符串,表示字符串数组words。接下来是两个整数left和right,表示区间的左右边界

    输出格式:输出一个整数,表示左闭右开区间[left,right)内所有元音字符串的数目。

求细胞数量 

    一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右任一方向若还是细胞数字则归为同一细胞,求给定矩形阵列的细胞个数。

    输入格式:第一行两个整数代表矩阵大小n和m。接下来n行,每行一个长度为m的只含字符0到9的字符串,代表这个n×m的矩阵。(1≤n,m≤100)

    输出格式:仅一行,一个整数代表细胞个数。

示例:

输入:

3 3

111

000

111

输出:

2

 (意思是一堆相邻的非0数字看做一个细胞)

 二叉树的后序遍历

    给定一个二叉树的根节点 root,返回其节点值的后序遍历。二叉树在输入中按层序遍历进行序列化表示,空节点用 0 表示。

    输入格式:输入的第一行是一个整数n,表示层序遍历序列的长度。输入的第二行是 n 个整数,表示二叉树的层序遍历序列,其中 0 表示空节点。

    输出格式:二叉树的后序遍历序列,空结点不需输出,最后一个无空格。

示例:

输入:

5

1 0 2 3 4

输出:

3 4 2 1

2024春

选择:

判断:

各种树的性质

填空

哈希表,成功失败查找长度;

计算:

某程序的时间复杂度

最大堆的建立与删除;

AVL树的建立,成功查找时间,失败查找时间;

算法:

给定一维数组,循环右移R位,在尽量小的时间空间复杂度内实现原数组的右移。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值