判断栈混洗
题目描述
判断一个输入序列是否为某一个序列的栈混洗。设输入序列为1-N的数字。
输入:
n,随后输入一个包含n个数字序列。范围从1到n的不同数字
输出:
如果是合法的栈混洗输出ture,否则输出false;
要求O(N)时间复杂度
样例输入输出
样例1
输入:
7
3 4 2 1 5 6 7
输出:
true
样例2
输入:
6
5 4 3 1 2 6
输出:
false
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int main()
{
stack<int>t;
int n;cin>>n;
vector<int>x;
stack<int>y;
for(int i=n;i>0;i--)
x.push_back(i);
int m;
for (int i=0;i<n;i++)
{
cin>>m;
y.push(m);
}
int book=0;
while(1)
{
if(!y.empty())
{
t.push(y.top());
y.pop();
}
while(!t.empty()&&x[book]==t.top())
{
t.pop();book++;
}
if(book>=n||y.empty()&&x[book]!=t.top())break;
}
if(t.empty())cout<<"true";
else cout<<"false";
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
Example
Input
1 0 10
-1 0 1 2 3 4 0 1 2 3
Output
1111101110
Input
1 1 6
-1 0 0 0 0 0
Output
100001
Input
1 1 6
-1 0 2 0 0 0
Output
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>
#include<string>
#include<stack>
using namespace std;
int main()
{
bool first,last;
cin>>first>>last;
int length;
cin>>length;
int *next;
next=new int [length];
for (int i=0;i<length;i++)
{
cin>>next[i];
}
if (next[0]!=-1||next[1]!=0)
{
cout<<"ERROR";
return 0;
}
bool *pattern;
pattern=new bool [length];
pattern[0]=first;
int k=0;
int n=1;
for (int i=2;i<length;i++)
{
if (next[i]==0)
{
pattern[i-1]=!first;
k=0;
n=1;
}
else
{
if (next[i] >= i || ( i != next[i] + 1 && pattern[i - next[i] - 1] ==pattern[0])) //错误:最大匹配长度过长或字符不匹配时不能回溯到正确位置
{
cout << "ERROR" << endl;
return 0;
}
int cur = pattern[next[i] - 1];
pattern[i - 1] = cur;
}
}
pattern[length-1]=last;
for (int i=0;i<length;i++)
{
cout<<pattern[i];
}
delete next;
delete pattern;
return 0;
}
互斥字符串
题目描述
给定一个仅含有英文大小写字母的字符串序列 s,若其中任意两个相邻字符都不是同一个字母的大小写形式,则称其为互斥字符串。
程序需要将给定的字符串转换为互斥字符串。aa为互斥,aA和Aa为非互斥。
程序的每次操作可以从字符串中选出满足上述条件的两个相邻字符并删除,直到字符串整理好为止。
注:若最终结果为空字符串,请输出 -1。
要求时间复杂度O(n)
Input Format
输入由一行字符串组成。测试样例保证答案唯一。
Output Format
输出一行,为输入字符串经过若干次删除操作得到的互斥字符串。
Example
Input
abBAcCc
Output
c
说明
该样例存在多种转换路径,但最终输出相同
“abBAcCc” --> “aAcCc” --> “cCc” --> “c”
“abBAcCc” --> “abBAc” --> “aAc” --> “c”
样例输入输出
样例1
输入:
abBAcCc
输出:
c
样例2
输入:
AaBbCcDd
输出:
-1
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string s;
cin>>s;
int a=abs('a'-'A');
for (int i=1;i<=signed(s.length())-1;i++)
{
if (abs(s[i]-s[i-1])==a)
{
s.erase(i-1,2);i=0;
}
}
if (s.empty())cout<<"-1";
else cout<<s;
return 0;
}
旋转的矩阵
题目描述
给定一个n*m的矩阵,请以顺、逆时针交替旋转的方式打印出每个元素。
Input Format
第一行n m; 0<n,m<100
后n行,每行m个整数。
Output Format
n*m个矩阵元素,空格隔开。
Example
Input
4 4
1 2 3 4
12 13 16 5
11 14 15 6
10 9 8 7
Output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
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 <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n;
int m;
cin>>n>>m;
vector<vector<int>>arr(n,vector<int>(m));
for (int i=0;i<n;i++)
{
for (int j=0;j<m;j++)
{
cin>>arr[i][j];
}
}
vector<int>out;
int round=min(m/2,n/2);
for (int i=0;i<=round;i++)
{
if (i==m-1-i)
{
for(int j=i;j<=n-1-i;j++)
{
out.push_back(arr[j][i]);
}
}
else if (i==n-1-i)
{
for(int j=i;j<=m-1-i;j++)
{
out.push_back(arr[i][j]);
}
}
//顺时针
else if (i%2==0)
{
for (int j=i;j<m-1-i;j++)
{
out.push_back(arr[i][j]);
}
for (int j=i;j<n-1-i;j++)
{
out.push_back(arr[j][m-1-i]);
}
for (int j=m-1-i;j>i;j--)
{
out.push_back(arr[n-1-i][j]);
}
for (int j=n-1-i;j>i;j--)
{
out.push_back(arr[j][i]);
}
}
else if (i%2==1)
{
for (int j=i;j<n-1-i;j++)
{
out.push_back(arr[j][i]);
}
for (int j=i;j<m-1-i;j++)
{
out.push_back(arr[n-1-i][j]);
}
for (int j=n-1-i;j>i;j--)
{
out.push_back(arr[j][m-1-i]);
}
for (int j=m-1-i;j>i;j--)
{
out.push_back(arr[i][j]);
}
}
}
for (int i=0;i<out.size();i++)
{
cout<<out[i]<<" ";
}
}
二元一次多项式求幂
题目描述
给定一个常数项为0的二元一次多项式,求该多项式的幂。
设未知数为x,y,输入为x和y的整数系数a,b以及整数幂n,输出形如以下样式
求幂运算的结果,按照x的幂降序排列
Input Format
输入未知数整数系数 a,b (-100<a,b<100),n (1<n<6)
Output Format
幂运算的结果的多项式,按照x幂降序排列
Example
Input
2 3 2
Output
4x2+12xy+9y2
说明
幂为1时不输出^1
系数为1时不输出系数,-1只输出负号。
样例输入输出
样例1
输入:
2 3 2
输出:
4x2+12xy+9y2
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
#define ll long long
int main()
{
double a,b;int n;
cin>>a>>b>>n;
ll*arr=new ll[n+1];
ll*cn=new ll[n+1];
for (int j=0;j<=n;j++)
{
ll s=1;
for (double i=n;i>=n-j+1;i--)
{
s=s*i;
}
for (double i=j;i>=1;i--)
{
s=s/i;
}
cn[j]=s;
}
int i=n;int j=0;
while(i>=0&&j<=n)
{
arr[j]=(pow(a,i)*pow(b,j))*cn[j];
i--;j++;
}
int x=n;int y=0;
for (int i=0;i<=n;i++,x--,y++)
{
if(arr[i] == 1){}
else if(arr[i] == -1)
{
cout << "-";
}
else
{
cout << arr[i];
}
if (x == 1)
{
cout << "x";
}
else if (x == 0){}
else
{
cout << "x^" <<x;
}
if (y == 1)
{
cout << "y";
}
else if (y == 0){}
else
{
cout << "y^" << y;
}
if (i<n&&arr[i+1]>0)
cout << "+";
}
//sb 問題居然是因爲double不夠大
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 <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <stack>
using namespace std;
int main()
{
string s;
cin>>s;
stack<string>temp;
int n=s.size();
for (int i=0;i<n;i++)
{
string p;
if (s[i]=='/')
{
int x=i+1;
while(x<n&&s[x]!='/')x++;
p=s.substr(i,x-i);
i=x-1;
}
if (p=="/."||p=="/")continue;
else if (!temp.empty()&&p=="/..")temp.pop();
else if (temp.empty()&&p=="/..")continue;
else temp.push(p);
}
if (temp.empty())cout<<"/"<<endl;
else
{
string x;
while (!temp.empty())
{
x=temp.top()+x;
temp.pop();
}
cout<<x;
}
return 0;
}
DS-表达式求值
题目描述
设计一个表达式求值的程序。该程序必须可以接受包含(,),+,-,*,/,%和^(求幂)的中缀表达式,并求出结果。如果表达式正确,则输出表达式的值,如果表达式非法,则输出错误信息。
注意223转为后缀应为223^^
操作数均转为double运算。
幂运算可以直接使用pow(a,b)
%,操作数转为Int再进行计算。
输入要求:
多个表达式,每个表达式占一行。
输出要求:
对每个表达式,如果为正确表达式则输出结果(精确到小数点后两位),如果为错误表达式则输出“ERROR IN INFIX NOTATION”.
样例输入输出
样例1
输入:
(2-4)^3
输出:
-8.00
样例2
输入:
(35(4+8)%2)
输出:
0.00
样例3
输入:
1+2(
输出:
ERROR IN INFIX NOTATION
#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 '/':
case '%':
return 2;
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())&&opnd.size()>=2&&s[g_pos]!='^') //乘方运算顺序由右到左,故留着到下一个阶段运算 //当前优先级小于栈顶优先级
{
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的二元一次多项式,求该多项式的幂。
设未知数为x,y,输入为x和y的整数系数a,b以及整数幂n,输出形如以下样式
求幂运算的结果,按照x的幂降序排列
Input Format
输入未知数整数系数 a,b (-1000<a,b<1000),n (2<n<20)
Output Format
幂运算的结果的多项式,按照x幂降序排列
Example
Input
99 100 15
Output
860058354641288524893953951499x15+13031187191534674619605362901500x14y+92139707414891638724482363950000x13y2+403305116630838822699754455000000x12y3+1222136717063147947575013500000000x11y4+2715859371251439883500030000000000x10y5+4572153823655622699495000000000000x9y6+5937862108643665843500000000000000x8y7+5997840513781480650000000000000000x7y8+4712108147752005000000000000000000x6y9+2855823119849700000000000000000000x5y10+1311213553650000000000000000000000x4y11+441486045000000000000000000000000x3y12+102910500000000000000000000000000x2y13+14850000000000000000000000000000xy14+1000000000000000000000000000000y15
说明
幂为1时不输出^1
系数为1时不输出系数,-1只输出负号。
样例输入输出
样例1
输入:
99 100 15
输出:
860058354641288524893953951499x15+13031187191534674619605362901500x14y+92139707414891638724482363950000x13y2+403305116630838822699754455000000x12y3+1222136717063147947575013500000000x11y4+2715859371251439883500030000000000x10y5+4572153823655622699495000000000000x9y6+5937862108643665843500000000000000x8y7+5997840513781480650000000000000000x7y8+4712108147752005000000000000000000x6y9+2855823119849700000000000000000000x5y10+1311213553650000000000000000000000x4y11+441486045000000000000000000000000x3y12+102910500000000000000000000000000x2y13+14850000000000000000000000000000xy14+1000000000000000000000000000000y15
#include<iostream>
#include<queue>
#include<string>
#include<string.h>
using namespace std;
//将数字的非符号部分存入字符串
string getNum(const string& s) {
int t = s.size();
string str = "";
if (s[0] == '-')
{
for (int i = 1; i < t; i++)
str += s[i];
}
else
{
for (int i = 0; i < t; i++)
str += s[i];
}
return str;
}
//乘法,逐位计算,将结果存入数组再转为字符串
string multi(const string& a, const string& b)
{
int len1, len2;
int isNeg = 0;
if (((a[0] == '-' && b[0] != '-') || (a[0] != '-' && b[0] == '-')) && (a != "0" && b != "0")) isNeg = 1;
string num1 = getNum(a);
string num2 = getNum(b);
len1 = num1.size();
len2 = num2.size();
int* res = new int[len1 + len2];
memset(res, 0, sizeof(int) * (len1 + len2));
for (int i = len1 - 1; i >= 0; --i)
{
for (int j = len2 - 1; j >= 0; --j) {
res[i + j + 1] += (num1[i] - '0') * (num2[j] - '0');
}
}
for (int i = len1 + len2 - 1; i >= 0; --i)
{
if (res[i] >= 10) {
res[i - 1] += res[i] / 10;
res[i] %= 10;
}
}
string ans = "";
for (int i = 0; i < len1 + len2; ++i) ans += res[i] + '0';
if (isNeg) ans = '-' + ans;
return ans;
}
//加法
string plusNum(const string& num1, const string& num2)
{
int len1 = num1.size(), len2 = num2.size();
int len = max(len1, len2) + 1;
int length = len;
string ans = "";
int* res = new int[length];
memset(res, 0, sizeof(int) * length);
while (len1 > 0 && len2 > 0)
{
res[len - 1] = (num1[len1 - 1] - '0') + (num2[len2 - 1] - '0');
len1--;
len2--;
len--;
}
while (len1 > 0)
{
res[len - 1] = (num1[len1 - 1] - '0');
len1--;
len--;
}
while (len2 > 0)
{
res[len - 1] = (num2[len2 - 1] - '0');
len2--;
len--;
}
for (int i = length - 1; i >= 0; --i)
{
if (res[i] >= 10)
{
res[i - 1] += res[i] / 10;
res[i] %= 10;
}
}
int k;
for (k = 0; k < length; k++)
if (res[k] != 0)break;
if (k == length)ans = "0";
else
{
for (int i = k; i < length; i++)
ans += res[i] + '0';
}
return ans;
}
//减法
string minusNum(string& num1, string& num2)
{
int len1 = num1.size();
int len2 = num2.size();
int len;
if (len1 >= len2)
{
for (int i = 1; i <= len1 - len2; i++)
num2 = '0' + num2;
len = len1;
}
if (len2 > len1)
{
for (int i = 1; i <= len2 - len1; i++)
num1 = '0' + num1;
len = len2;
}
int* num_a = new int[len];
int* num_b = new int[len];
for (int i = 0; i < len; ++i)
{
num_a[i] = num1[i] - '0';
num_b[i] = num2[i] - '0';
}
int q = 0;//记录退位
for (int i = len - 1; i >= 0; --i)
{
num_a[i] -= q;
if (num_a[i] < num_b[i]) {
num_a[i] += 10;
q = 1;
}
num_b[i] = num_a[i] - num_b[i];
}
int k;
string ans = "";
for (k = 0; k < len; k++)
if (num_b[k] != 0)break;
if (k == len)ans = "0";
else
{
for (int i = k; i < len; i++)
ans += num_b[i] + '0';
}
return ans;
}
//判断两数相减结果是否为非负
bool isPos(const string&str1, const string str2)
{
if (str1.size() > str2.size())
return true;
if (str1.size() == str2.size())
return str1 > str2;
return false;
}
//计算系数
void powerFun(queue<string>& q, int n, const string& a, const string& b)
{
string t = "0";
string s;
string num1, num2;
string ans;
for (int i = 2; i <= n; i++)
{
q.push(to_string(0));
for (int j = 1; j <= i + 1; j++)
{
s = q.front();
q.pop();
num1 = multi(t, b);
num2 = multi(s, a);
if (num1[0] != '-' && num2[0] != '-')
ans = plusNum(num1, num2);
else if (num1[0] == '-' && num2[0] == '-')
{
ans = plusNum(getNum(num1), getNum(num2));
ans = '-' + ans;
}
if (num1[0] == '-' && num2[0] != '-')
{
num1 = getNum(num1);
if (isPos(num2, num1))
{
ans = minusNum(num2, num1);
}
else
{
ans = '-' + minusNum(num1, num2);
}
}
if (num1[0] != '-' && num2[0] == '-')
{
num2 = getNum(num2);
if (isPos(num1, num2))
{
ans = minusNum(num1, num2);
}
else
{
ans = '-' + minusNum(num2, num1);
}
}
q.push(ans);
t = s;
}
}
}
//表达式输出处理
void showRes(queue<string>& q, int n)
{
int k = n;
int flag = 1;
while (!q.empty())
{
if (q.front() == "0" )
{
q.pop();
k--;
flag = 0;
continue;
}
else if (q.front() == "1")
{
if (flag != 0 && k < n)cout << '+';
flag = 1;
}
else if (q.front()[0] != '-')
{
if (k < n)cout << '+';
cout << q.front();
}
else if (q.front() == "-1") cout << '-';
else if (q.front()[0] == '-') cout << q.front();
if (k == 1) cout << 'x';
else if (k != 0) cout << "x^" << k;
if (k == n - 1) cout << 'y';
else if (k != n) cout << "y^" << n - k;
q.pop();
k--;
}
cout << endl;
}
int main()
{
int a, b, n;
cin >> a >> b >> n;
queue<string>q;
string str1 = to_string(a);
string str2 = to_string(b);
q.push(str1);
q.push(str2);
powerFun(q, n, str1, str2);
showRes(q, n);
return 0;
}
二叉树遍历及二叉树高度
题目描述
给出一棵二叉树的先序遍历和中序遍历序列,计算该二叉树的高度。其中,二叉树的先序和中序遍历序列为不包含重复英文字母(区别大小写)的字符串。
Input Format
二叉树结点的总个数n<=50
然后输入先序和中序遍历序列,两个序列长度均为n。
Output Format
二叉树高度(整数) ,叶子结点高度为1
Example
Input
9
ABDGHCEIF
GDHBAEICF
Output
4
样例输入输出
样例1
输入:
9
ABDGHCEIF
GDHBAEICF
输出:
4
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
unordered_map<char,int>dic;
vector<char>pre;
vector<char>in;
struct TreeNode
{
char val;
TreeNode* left;
TreeNode* right;
TreeNode():left(nullptr),right(nullptr){}
TreeNode(char x):val(x),left(nullptr),right(nullptr){}
};
TreeNode* prein(int root,int left,int right)
{
if (left>right)
{
return nullptr;
}
TreeNode *node=new TreeNode(pre[root]);
int i=dic[pre[root]];
node->left=prein(root+1,left,i-1);
node->right=prein(root+i-left+1,i+1,right);
return node;
}
int height(TreeNode* root)
{
if (!root)return 0;
return max(height(root->left),height(root->right))+1;
}
int main()
{
int n;
cin>>n;
char t;
for (int i=0;i<n;i++)
{
cin>>t;
pre.push_back(t);
}
for (int i=0;i<n;i++)
{
cin>>t;
in.push_back(t);
}
for (int i=0;i<in.size();i++)
{
dic[in[i]]=i;
}
cout<<height(prein(0,0,in.size()-1));
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
Example
Input
5
4
0 4
2 4
0 2
1 3
2
3 4
2 4
Output
false
true
样例输入输出
样例1
输入:
5
4
0 4
2 4
0 2
1 3
2
3 4
2 4
输出:
false
true
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int n;
int *boss;
int findboss(int x)
{
boss[x]=boss[x]!=x ?findboss(boss[x]):x;
return boss[x];
}
void uniontion(int x,int y)
{
int a=findboss(x);
int b=findboss(y);
if (a==b)return;
a>b?boss[b]=a:boss[a]=b;
}
bool isconnect(int x,int y)
{
return findboss(x)==findboss(y);
}
int main()
{
cin>>n;
boss=new int[n];
for (int i=0;i<n;i++)
{
boss[i]=i;
}
int m;
cin>>m;
int x;int y;
for (int i=0;i<m;i++)
{
cin>>x>>y;
uniontion(x,y);
}
int p;
cin>>p;
for (int i=0;i<p;i++)
{
cin>>x>>y;
if (isconnect(x,y))cout<<"true"<<endl;
else cout<<"false"<<endl;
}
//system("pause");
return 0;
}
判断是否为堆-堆整理
题目描述
请判断输入的整数序列是否为堆。
如果为最大堆,请输出“max ”以及整理后的最小堆,整数序列数字之间有空格,最后无空格。
如果为最小堆,请输出“min ” 以及整理后的最大堆,整数序列数字之间有空格,最后无空格。
如果不为堆,请输出整理后的最大堆,整数序列数字之间有空格,最后无空格。
如果既是最大堆也是最小堆,请只输出“max min ”
Input Format
先输入整数序列个数n 0<n<1000
然后输入n个整数序列,整数取值范围【-100000,100000】
Output Format
最大堆或最小堆序列
Example
Input
10
-8 8 -9 10 -2 1 -6 -9 7 2
Output
10 8 1 7 2 -9 -6 -9 -8 -2
Input
10
10 8 1 7 2 -9 -6 -9 -8 -2
Output
max -9 -9 -6 -8 -2 1 10 7 8 2
Input
10
-9 -9 -6 -8 -2 1 10 7 8 2
Output
min 10 8 1 7 2 -9 -6 -9 -8 -2
Input
3
1 1 1
Output
max min
注意:序列最后无空格,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;
void IsHeap(int num[], int n)
{
bool ismax=1;bool ismin=1;
int b=n;
while (b/2>0)
{
if (num[b]>num[b/2]){ismax=0;break;}
b--;
}
b=n;
while (b/2>0)
{
if (num[b]<num[b/2]){ismin=0;break;}
b--;
}
if (ismin&&ismax)flag=1;
else if (ismax)flag=2;
else if (ismin)flag=3;
else flag=4;
}
void BuildMaxHeap(int num[], int n) //生成最大堆
{
for (int i=n/2;i>0;i--)
{
int t=num[i];
int c=i*2;
while(c<=n)
{
if (c<n&&num[c]<=num[c+1])c++;
if(num[c]>t){num[c/2]=num[c];c*=2;}
else break;
}
num[c/2]=t;
}
}
void BuildMinHeap(int num[], int n) //生成最小堆
{
for (int i=n/2;i>0;i--)
{
int t=num[i];
int c=i*2;
while(c<=n)
{
if (c<n&&num[c]>=num[c+1])c++;
if(num[c]<t){num[c/2]=num[c];c*=2;}
else break;
}
num[c/2]=t;
}
}
void BuildHeap(int num[], int n)
{
if (flag==1)
{
cout<<"max min ";
return ;
}
else if (flag==2)
{
cout<<"max ";
BuildMinHeap(num,n);
}
else if(flag==3)
{
cout<<"min ";
BuildMaxHeap(num,n);
}
else if (flag==4)
{
BuildMaxHeap(num,n);
}
for (int i=1;i<n;i++)
{
cout<<num[i]<<" ";
}
cout<<num[n];
}
int main() {
int n;
cin>>n;
int *num=new int[n+1];
for (int i=1;i<=n;i++)
{
cin>>num[i];
}
IsHeap(num, n);
BuildHeap(num, n);
//system("pause");
return 0;
}
完全二叉树的先序遍历
题目描述
给出一棵完全二叉树的先序遍历,输出其后序遍历。结点均为不重复的单个英文字母,区分大小写。结点总数小于52。
Input Format
输入先序字符串
Output Format
后序遍历字符串
Example
Input
ABDGHCEIF
Output
GHDCBIFEA
样例输入输出
样例1
输入:
ABDGHCEIF
输出:
GHDCBIFEA
样例2
输入:
a
输出:
a
#include<iostream>
#include<string>
using namespace std;
int pos;
void pretrav(string &pct,char* ct,int r,int len)
{
if(r<=len)
{
ct[r]=pct[pos++];
pretrav(pct,ct,r*2,len);
pretrav(pct,ct,r*2+1,len);
}
}
void posttrav(char* ct,int r,int len)
{
if(r<=len)
{
posttrav(ct,r*2,len);
posttrav(ct,r*2+1,len);
cout<<ct[r];
}
}
int main()
{
string input;
cin>>input;
char* ct=new char[input.size()+1];
pretrav(input,ct,1,input.size());
posttrav(ct,1,input.size());
delete ct;
}
求整数最大间隔-性能
题目描述
请输出数字序列的最大间隔。
请使用以下伪随机数生成函数 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>
using namespace std;
int n,seed;
int randI() {
return(((seed = seed * 214013L + 2531011L) >> 16) & 0x7fff);
}
int rand32() {
return ((randI() << 16) + (randI() << 1) + randI() % 2);
}
int maxGap(int arr[]) {
int maxGap=0;
int minN = arr[0], maxN = arr[0];
//遍历找到数组中最大值最小值。
for (int i = 0; i < n; ++i)
{
if (arr[i] > maxN)maxN = arr[i];
if (arr[i] < minN)minN = arr[i];
}
if (maxN == minN)return 0;
bool *harsh=new bool[n]{0};
int*mins=new int[n];
int *maxs=new int[n];
double gap=double(maxN-minN)/(n-1);//im double为了让分桶更加均匀!!!
for (int i = 0; i < n; i++)
{
int indix=int((arr[i]-minN)/gap);//im 分桶均匀的情况下让下标成为整数
if (harsh[indix])
{
mins[indix]=min(mins[indix],arr[i]);
maxs[indix]=max(maxs[indix],arr[i]);
}
else
{
mins[indix]=maxs[indix]=arr[i];
harsh[indix]=1;
}
}
int lastMax=maxs[0];
for (int i = 1; i < n; i++)
{
if(harsh[i])
{
maxGap=max(maxGap,mins[i]-lastMax);
lastMax=maxs[i];
}
}
delete[]maxs;
delete[]mins;
delete []harsh;
return maxGap;
}
int main() {
cin >> n >> seed;
int* arr = new int[n];
for (int i = 0; i < n; ++i)
arr[i] = rand32();
cout << maxGap(arr) << endl;
delete[]arr;
//system("pause");
return 0;
}
创建AVL树并判断是否为完全二叉树
题目描述
在AVL树中,任何节点的两个子树的高度最多相差1;如果它们高度相差不止1,则需要重新平衡以恢复这种属性。
现在给定一个插入序列, 一个一个地将键值插入初始为空的AVL树中,输出得到的AVL树的层次顺序遍历序列,并判断它是否是一个完全二叉树。
输入格式:
第一行包含一个正整数N(<= 20)。然后在下一行给出N个不同的整数键。所有数字都用空格隔开。
输出格式:
第一行打印得到的AVL树的层次顺序遍历序列。所有数字都必须用空格隔开,并且行尾必须没有多余的空格。然后在下一行中,如果树为完全二叉树,则打印“Yes”;如果不是,则打印“No”。
样例输入1:
5
88 70 61 63 65
样例输出1:
70 63 88 61 65
Yes
样例输入2:
10
62 88 58 47 35 73 51 99 37 93
样例输出2:
62 47 88 35 58 73 99 37 51 93
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<iostream>
#include<queue>
#include<algorithm>
using namespace std;
//树结点
struct TreeNode
{
int val;
int height;
TreeNode* left;
TreeNode*right;
TreeNode():val(0),left(nullptr),right(nullptr),height(1){}
TreeNode(int x):val(x),left(nullptr),right(nullptr),height(1){}
TreeNode(int x,TreeNode*left,TreeNode*right):val(x),height(1),left(left),right(right){}
};
//某树是不是完全二叉树
bool isbinarytree(TreeNode*root)
{
queue<TreeNode*>que;
que.push(root);
TreeNode *cur;
//遇到空结点
while((cur=que.front())!=nullptr)
{
que.pop();
que.push(cur->left);
que.push(cur->right);
}
//验证que里面还有没有数
while(!que.empty())
{
if (que.front()!=nullptr)
{
return false;
}
que.pop();
}
return true;
}
//层次遍历输出数组
vector<int> levelorder(TreeNode*root)
{
vector<int>arr;
if (root)
{queue<TreeNode*>que;
que.push(root);
while (!que.empty())
{
auto x=que.front();
arr.push_back(x->val);
que.pop();
if (x->left)que.push(x->left);
if (x->right)que.push(x->right);
}
}
return arr;
}
//getheight(递归)
int getheight(TreeNode* root)
{
if (!root)return 0;
return root->height;
}
//LL右单旋
TreeNode* rightrotate(TreeNode* root)
{
TreeNode* temp=root->left;
root->left=temp->right;
temp->right=root;
root->height=max(getheight(root->left),getheight(root->right))+1;
temp->height=max(getheight(temp->left),getheight(temp->right))+1;
return temp;
}
//RR左单旋
TreeNode* leftrotate(TreeNode* root)
{
TreeNode* temp=root->right;
root->right=temp->left;
temp->left=root;
root->height=max(getheight(root->left),getheight(root->right))+1;
temp->height=max(getheight(temp->left),getheight(temp->right))+1;
return temp;
}
//LR 对root->left做左单旋,再对root做右单旋
TreeNode* lerigrotate(TreeNode* root)
{
root->left=leftrotate(root->left);
return rightrotate(root);
}
//RL 对root-right做右单旋,再对root做左单旋
TreeNode* riglerotate(TreeNode* root)
{
root->right=rightrotate(root->right);
return leftrotate(root);
}
//把数据插入到avl树上
TreeNode* insert(TreeNode * root,int key)
{
if (!root)
{
root=new TreeNode(key);
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=lerigrotate(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=riglerotate(root);
}
}
}
root->height=max(getheight(root->left),getheight(root->right))+1;
return root;
}
bool isdelete=1;
//删除叶子结点的方法删除avl结点
TreeNode* deletekey(TreeNode* root,int key)
{
if (!root) {isdelete=0;return root;}//没成功删除
if (root->val==key)//删除叶子结点
{
if(!root->left&&!root->right){root=nullptr;return root;}
if (getheight(root->left)>=getheight(root->right))//替换并且使得要删除的元素变成叶子结点
{
//对左孩子找到最里面的右孩子,改变key,迭代删掉它
TreeNode* temp=root->left;
while (temp->right)
{
temp=temp->right;
}
root->val=temp->val;
key=temp->val;
root->left=deletekey(root->left,key);
if (getheight(root->right)-getheight(root->left)==2)root=leftrotate(root);
}
else
{
TreeNode* temp=root->right;
while (temp->left)
{
temp=temp->left;
}
root->val=temp->val;
key=temp->val;
root->right=deletekey(root->right,key);
if (getheight(root->left)-getheight(root->right)==2)root=rightrotate(root);
}
}
else if(key<root->val)
{
root->left=deletekey(root->left,key);
if (getheight(root->right)-getheight(root->left)==2)root=leftrotate(root);
}
else if(key>root->val)
{
root->right=deletekey(root->right,key);
if (getheight(root->left)-getheight(root->right)==2)root=rightrotate(root);
}
root->height=max(getheight(root->left),getheight(root->right))+1;
return root;
}
int main()
{
int n;
cin >> n;
TreeNode* root = NULL;
for(int i = 1; i <= n; i++)
{
int x;
cin >> x;
root = insert(root, x);
}
vector<int>arr=levelorder(root);
for (int i = 0; i < arr.size()-1; i++)cout<<arr[i]<<" ";
cout<<arr[arr.size()-1]<<endl;
if (isbinarytree(root))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
/*int m;
cin>>m;
root=deletekey(root,m);
if (isdelete)cout<<"删除成功"<<endl;
else cout<<"删除失败"<<endl;
arr=levelorder(root);
for (int i = 0; i < arr.size()-1; i++)cout<<arr[i]<<" ";
cout<<arr[arr.size()-1]<<endl;
if (isbinarytree(root))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
system ("pause");*/
return 0;
}
ds-多源最短路径
样例输入输出
样例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
Dijkstra
//最短路径
/*
1.Floyd-Warshall(无法解决负权回路)(多源)
2.Dijkstra--(权不能为负)(单源)
3.BFS遍历
*/
#include<iostream>
using namespace std;
#define inf 0x7fffffff
int main()
{
int n,m;
cin>>n>>m;
int **e=new int *[n];
for (int i = 0; i < n; i++)
{
e[i]=new int[n];
}
for (int i = 0; i <n; i++)
{
for(int j=0;j<n;j++)
{
if(i==j)e[i][j]=0;
else e[i][j]=inf;
}
}
int u,v,w;
for(int i=0;i<m;i++)
{
cin>>u>>v>>w;
e[u][v]=w;
}
//Dijkstra
int **dic=new int*[n];
for (int i = 0; i < n; i++)
{
dic[i]=new int [n];
}
for (int k = 0; k <n; k++)
{
for(int i=0;i<n;i++)dic[k][i]=e[k][i];
int *book=new int[n]{0};
book[k]=1;
int j;
for (int i = 0; i < n; i++)
{
int min=inf;
for (int i = 0; i < n; i++)
{
if (book[i]==0&&dic[k][i]<min)
{
min=dic[k][i];j=i;
}
}
book[j]=1;
for (int i = 0; i < n; i++)
{
if (e[j][i]<inf&&dic[k][i]>dic[k][j]+e[j][i])
{
dic[k][i]=dic[k][j]+e[j][i];
}
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n-1;j++)
{
if(dic[i][j]==inf)cout<<"-1"<<" ";
else cout<<dic[i][j]<<" ";
}
if(dic[i][n-1]==inf)cout<<"-1";
else cout<<dic[i][n-1];
cout<<endl;
}
//system("pause");
return 0;
}
Floyd-Warshall
//最短路径
/*
1.Floyd-Warshall(无法解决负权回路)(多源)
2.Dijkstra--(权不能为负)(单源)
3.BFS遍历
*/
#include<iostream>
using namespace std;
#define inf 0x7fffffff
int main()
{
int n,m;
cin>>n>>m;
int **e=new int *[n];
for (int i = 0; i < n; i++)
{
e[i]=new int[n];
}
for (int i = 0; i <n; i++)
{
for(int j=0;j<n;j++)
{
if(i==j)e[i][j]=0;
else e[i][j]=inf;
}
}
int u,v,w;
for(int i=0;i<m;i++)
{
cin>>u>>v>>w;
e[u][v]=w;
}
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(e[i][k]<inf&&e[k][j]<inf&&e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n-1;j++)
{
if(e[i][j]==inf)cout<<"-1"<<" ";
else cout<<e[i][j]<<" ";
}
if(e[i][n-1]==inf)cout<<"-1";
else cout<<e[i][n-1];
cout<<endl;
}
//system("pause");
return 0;
}
Dijkstra单源最短路径
样例输入输出
样例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
//最短路径
/*
1.Floyd-Warshall(无法解决负权回路)(多源)
2.Dijkstra--(权不能为负)(单源)
3.BFS遍历
*/
#include<iostream>
#include<vector>
using namespace std;
#define inf 0x7fffffff
int main()
{
int n,m;
cin>>n>>m;
int **e=new int *[n+1];
for (int i = 1; i <= n; i++)
{
e[i]=new int[n+1];
}
for (int i = 1; i <=n; i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)e[i][j]=0;
else e[i][j]=inf;
}
}
int u,v,w;
for(int i=0;i<m;i++)
{
cin>>u>>v>>w;
e[u][v]=w;
}
//Dijkstra
int k;
cin>>k;
int *dic=new int[n+1];
for(int i=1;i<=n;i++)dic[i]=e[k][i];
int *book=new int[n+1]{0};
book[k]=1;
int *j=new int[n]{0};
vector<vector<int>>path(n+1,vector<int>());
for (int x = 1; x < n; x++)
{
int min=inf;
for (int i = 1; i <=n; i++)
{
if (book[i]==0&&dic[i]<min)
{
min=dic[i];j[x]=i;
}
}
book[j[x]]=1;
if (j[x])
{
cout<<"No."<<x<<" : "<<k;
auto c=path[j[x]].begin();
while (c!=path[j[x]].end())
{
cout<<" -> "<<*c;
c++;
}
cout<<" -> "<<j[x]<<" , d = "<<dic[j[x]]<<endl;
}
else{
cout<<"No."<<x<<" : No Path to";
for (int i = 1; i <=n; i++)
{
if (book[i]==0)
{
cout<<" "<<i;
}
}
break;
}
for (int i = 1; i <= n; i++)
{
if (e[j[x]][i]<inf&&dic[i]>dic[j[x]]+e[j[x]][i])
{
dic[i]=dic[j[x]]+e[j[x]][i];path[i]=path[j[x]];path[i].push_back(j[x]);
}
}
}
//system("pause");
return 0;
}
ds-求最大收益
题目描述
已知某一只股票的每一日收盘价格,假设只可以进行一次先买后卖,求每股最大收益。
输入:
先输入包含的股票价格数量,然后输入股票价格(大于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 i, s, res;
s = prices[0];
res = 0;
for (i = 0; i < prices.size(); i++)
{
s = min(s, prices[i]);
res = max(res, prices[i] - s);
}
if (res > 0)
{
return res;
}
else
{
return 0;
}
}
int main()
{
int length;
cin >> length;
vector<int> prices;
int temp;
for (int i = 0; i < length; i++)
{
cin >> temp;
prices.push_back(temp);
}
cout << maxProfit(prices);
}
创建RB树
题目描述
RB(红黑)树除了是一个二叉搜索树之外,还满足下面规则:
1)每个结点要么是红的,要么是黑的。
2)根结点是黑的。
3)每个叶结点,即空结点是黑的。
4)如果一个结点是红的,那么它的俩个儿子都是黑的。
5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
在给定插入序列的情况下,创建RB树,并输出最大值、最小值。
输入格式:
对于每种情况,第一行包含一个正整数N(<=20)。后边为N个不同的整数值,每个整数值以空格隔开。
第二行为要删除的节点个数M,后边为M个不同的整数值,以空格隔开。
输出格式:
第一行为RB树的前序遍历序列,以空格隔开,其中节点值后使用(B)和®表示节点的颜色;
第二行为RB树的最大值,最小值,以空格隔开;
第三行为删除M个节点之后的RB树的前序遍历序列,以空格隔开,若树为空,则输出Null;
样例输入1:
13 1 45 34 98 9 4 35 23 36 37 90 85 80
3 85 27 9
样例输出1:
34(B) 4(B) 1(B) 9(B) 23® 45(B) 36(B) 35® 37® 90® 85(B) 80® 98(B)
1 98
34(B) 4(B) 1(B) 23(B) 45(B) 36(B) 35® 37® 90® 80(B) 98(B)
样例输入2:
3 18 2 7
0
样例输出2:
7(B) 2® 18®
2 18
7(B) 2® 18®
注意:遍历输出最后一个结点有空格。删除带有双子结点时,找直接后继。
样例输入输出
样例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® 45(B) 36(B) 35® 37® 90® 85(B) 80® 98(B)
1 98
34(B) 4(B) 1(B) 23(B) 45(B) 36(B) 35® 37® 90® 80(B) 98(B)
样例2
输入:
3 18 2 7
0
输出:
7(B) 2® 18®
2 18
7(B) 2® 18®
#include<iostream>
using namespace std;
enum RBTcolor {B, R};
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 PreOrderNode(TreeNode* tree)const;
void RightRotate(TreeNode* node);
void LeftRotate(TreeNode* node);
void InsertNode(TreeNode* node);
void InsertFix(TreeNode* node);
void DeleteNode(TreeNode* node);
void DeleteFix(TreeNode* node, TreeNode* parent);
public:
RBTree() { root = NULL; }
~RBTree(){}
void Insert(int _data);
void Delete(int _data);
void FindMaxMin();
void PreOrder();
};
void RBTree::Insert(int _data)
{
TreeNode* newNode;
newNode = new TreeNode(_data, B, NULL, NULL, NULL);
InsertNode(newNode);
}
void RBTree::InsertNode(TreeNode* node)
{
if (root == NULL)
{
root = node;
return;
}
TreeNode* tmp = root, * ptmp;
while (tmp)
{
ptmp = tmp;
if (node->data < tmp->data)
tmp = tmp->left;
else
tmp = tmp->right;
}
if (node->data < ptmp->data)
ptmp->left = node;
else ptmp->right = node;
node->parent = ptmp;
node->color = R;
InsertFix(node);
}
void RBTree::InsertFix(TreeNode* node)
{
TreeNode* parent;
while ((parent = node->parent) && parent->color == R)
{
TreeNode* gparent = node->parent->parent;
//父节点是祖父节点的左孩子。
if (parent == gparent->left)
{
TreeNode* uncle = gparent->right;
//情况1:叔结点为红色。
if (uncle && uncle->color == R)
{
uncle->color = B;
parent->color = B;
gparent->color = R;
node = gparent;
continue;
}
//情况2:叔结点为黑色,插入节点为父节点的右孩子。
if (node == parent->right)
{
LeftRotate(parent);
swap(parent, node);
}
parent->color = B;
gparent->color = R;
RightRotate(gparent);
}
//父节点是祖父节点的右孩子。
if (parent == gparent->right)
{
TreeNode* uncle = gparent->left;
if (uncle && uncle->color == R)
{
uncle->color = B;
parent->color = B;
gparent->color = R;
node = gparent;
continue;
}
if (node == parent->left)
{
RightRotate(parent);
swap(parent, node);
}
parent->color = B;
gparent->color = R;
LeftRotate(gparent);
}
}
root->color = B;
}
void RBTree::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 == NULL)
root = lchild;
else
{
if (node == node->parent->left)node->parent->left = lchild;
else node->parent->right = lchild;
}
lchild->right = node;
node->parent = lchild;
}
void RBTree::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 == NULL)
root = rchild;
else
{
if (node == node->parent->left)node->parent->left = rchild;
else node->parent->right = rchild;
}
rchild->left = node;
node->parent = rchild;
}
void RBTree::PreOrderNode(TreeNode* tree)const
{
if (tree == NULL)return;
cout << tree->data;
if (tree->color == B)cout << "(B) ";
else cout << "(R) ";
PreOrderNode(tree->left);
PreOrderNode(tree->right);
}
void RBTree::PreOrder()
{
if (root == NULL)cout << "Null";
else PreOrderNode(root);
cout << endl;
}
void RBTree::FindMaxMin()
{
TreeNode* tmp1 = root;
TreeNode* tmp2 = root;
while (tmp1->left) tmp1 = tmp1->left;
while (tmp2->right)tmp2 = tmp2->right;
cout << tmp1->data << ' ' << tmp2->data << endl;
}
//找到要删除的节点。
void RBTree::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 == NULL)return;
DeleteNode(tmp);
}
void RBTree::DeleteNode(TreeNode* node)
{
RBTcolor tcolor = B;
if (node->left && node->right)
{
TreeNode* tmp = node->right;
while (tmp->left)tmp = tmp->left;
node->data = tmp->data;
if (tmp->parent == node)node->right = tmp->right;
else tmp->parent->left = tmp->right;
if (tmp->right)tmp->right->parent = tmp->parent;
tcolor = tmp->color;
if (tcolor == B)DeleteFix(tmp->right, tmp->parent);
delete tmp;
return;
}
else if (node->left)
{
if (node->parent == NULL)
{
root = node->left;
node->left->parent = NULL;
}
else
{
if (node == node->parent->left)node->parent->left = node->left;
else node->parent->right = node->left;
if (node->left)node->left->parent = node->parent;
tcolor = node->color;
}
if (tcolor == B)DeleteFix(node->left, node->parent);
delete node;
}
else
{
if (node->parent == NULL)
{
root = node->right;
if (node->right)node->right->parent = NULL;
}
else
{
if (node == node->parent->left)node->parent->left = node->right;
else node->parent->right = node->right;
if (node->right)node->right->parent = node->parent;
tcolor = node->color;
}
if (tcolor == B)DeleteFix(node->right, node->parent);
delete node;
}
}
void RBTree::DeleteFix(TreeNode* node, TreeNode* parent)
{
TreeNode* other;
while ((!node || node->color == B) && node != root)
{
if (node == parent->left)
{
other = parent->right;
if (other->color == R)
{
other->color = B;
parent->color = R;
LeftRotate(parent);
other = parent->right;
}
if ((!other->left || other->left->color == B) && (!other->right || other->right->color == B))
{
other->color = R;
node = parent;
parent = node->parent;
}
else
{
if (!other->right || other->right->color == B)
{
other->left->color = B;
other->color = R;
RightRotate(other);
other = parent->right;
}
other->color = other->parent->color;
parent->color = B;
other->right->color = B;
LeftRotate(parent);
node = root;
break;
}
}
else
{
other = parent->left;
if (other->color == R)
{
other->color = B;
parent->color = R;
RightRotate(parent);
other = parent->left;
}
if ((!other->left || other->left->color == B) && (!other->right || other->right->color == B))
{
other->color = R;
node = parent;
parent = node->parent;
}
else
{
if (!other->left || other->left->color == B)
{
other->right->color = B;
other->color = R;
LeftRotate(other);
other = parent->left;
}
other->color = parent->color;
parent->color = B;
other->left->color = B;
RightRotate(parent);
node = root;
break;
}
}
}
if (node)
node->color = B;
}
int main()
{
int n, m;
int num1, * num2;
cin >> n;
RBTree t;
for (int i = 0; i < n; i++)
{
cin >> num1;
t.Insert(num1);
}
cin >> m;
num2 = new int[m];
for (int i = 0; i < m; i++)
{
cin >> num2[i];
}
t.PreOrder();
t.FindMaxMin();
for(int i = 0; i < m; i++)
{
t.Delete(num2[i]);
}
t.PreOrder();
return 0;
}
消除连通图多余的边
样例输入输出
样例1
输入:
5 5
1 2 8
1 3 1
1 5 3
2 4 5
3 4 2
输出:
8
kruskal
//最小生成树
//1.prim
//2.Krusiul
#include<iostream>
#include<algorithm>
using namespace std;
struct Edge
{
int u,v,w;
bool operator <(struct Edge& edge) //因为要用sort()进行排序,重载运算符'<'
{
return w<edge.w;
}
}e[10005];
int n,m,par[10005];
int unionfind(int x)//归并集
{
return x==par[x]?x:par[x]=unionfind(par[x]);
}
int kruskal()
{
int cnt=0,ans=0;
sort(e,e+m);
for(int i=0;i<m;++i)//在for循环中,i++和++i都是在for循环内的语句执行后才执行!
{
int fu=unionfind(e[i].u),fv=unionfind(e[i].v);
if(fu!=fv)
{
ans+=e[i].w;
par[fu]=fv;
if(++cnt==n-1)return ans;//已经有n-1条边
}
}
}
int main()
{
int sum=0;
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>e[i].u>>e[i].v>>e[i].w;
sum+=e[i].w;
}
for(int i=1;i<=n;i++)
{
par[i]=i;
}
cout<<sum-kruskal()<<endl;
}
prim+邻接矩阵
//prim+邻接矩阵
#include<iostream>
#include<fstream>
using namespace std;
#define MAX 100
#define MAXCOST 0x7fffffff
int graph[MAX][MAX];
int prim(int graph[][MAX], int n)
{
int lowcost[MAX];
int mst[MAX];
int i, j, min, minid, sum = 0;
for (i = 2; i <= n; i++)
{
lowcost[i] = graph[1][i];
mst[i] = 1;
}
mst[1] = 0;
for (i = 2; i <= n; i++)
{
min = MAXCOST;
minid = 0;
for (j = 2; j <= n; j++)
{
if (lowcost[j] < min && lowcost[j] != 0)
{
min = lowcost[j];
minid = j;
}
}
sum += min;
lowcost[minid] = 0;
for (j = 2; j <= n; j++)
{
if (graph[minid][j] < lowcost[j])
{
lowcost[j] = graph[minid][j];
mst[j] = minid;
}
}
}
return sum;
}
int main()
{
int i, j, k, m, n;
int x, y, cost;
cin>>m>>n;//m point |n bian
//初始化图G
for (i = 1; i <= m; i++)
{
for (j = 1; j <= m; j++)
{
graph[i][j] = MAXCOST;
}
}
//构建图G
int sum=0;
for (k = 1; k <= n; k++)
{
cin>> i >> j >> cost;
graph[i][j] = cost;
graph[j][i] = cost;
sum+=cost;
}
//求解最小生成树
cout<<sum-prim(graph, m)<<endl;
//system("pause");
return 0;
}
prim
正常思路
#include<iostream>
using namespace std;
#define max 214748367
int main()
{
int m,n;
cin>>n>>m;
int **e=new int*[n+1];
for (int i = 0; i < n+1; i++)
{
e[i]=new int[n+1];
}
for (int i = 0; i < n+1; i++)
{
for (int j = 0; j < n+1; j++)
{
if(i==j)e[i][j]=0;
else e[i][j]=max;
}
}
int u,v,w;
int all=0;
for (int i = 0; i <m; i++)
{
cin>>u>>v>>w;
e[u][v]=w;
e[v][u]=w;
all+=w;
}
int *dis=new int[n+1];
for (int i = 1; i <= n; i++)
{
dis[i]=e[1][i];
}
int *book=new int[n+1]{0};
book[1]=1;
int count=0;
int j;
int sum=0;
while(count<n-1)
{
int min=max;
for (int i = 1; i <= n; i++)
{
if (book[i]==0&&dis[i]<min)
{
min=dis[i];j=i;
}
}
book[j]=1;
sum+=dis[j];
for (int i = 1; i <= n; i++)
{
if (book[i]==0&&dis[i]>e[j][i])
{
dis[i]=e[j][i];
}
}
count++;
}
cout<<all-sum<<endl;
return 0;
}
构造连通图使构造所消耗代价最小![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8ea56665dbec4a473f22469b31e9c1e4.png)
样例输入输出
样例1
输入:
4
0 6692 8925 9679
6692 0 9526 656
8925 9526 0 2664
9679 656 2664 0
2
1 3
1 2
输出:
656
#include<iostream>
using namespace std;
#define max 214748367
int main()
{
int n;
cin>>n;
int **e=new int* [n+1];
for (int i = 0; i < n+1; i++)
{
e[i]=new int[n+1];
}
for (int i = 1; i <=n; i++)
{
for (int j = 1; j <=n; j++)
{
cin>>e[i][j];
}
}
int m;
cin>>m;
int u,v;
for (int i = 0; i < m; i++)
{
cin>>u>>v;
e[u][v]=0;
e[v][u]=0;
}
//prim
int *dic=new int [n+1];
for (int i = i; i <= n; i++)
{
dic[i]=e[1][i];
}
int j;
int count=0;
int *book=new int [n+1]{0};
book[1]=1;
int sum=0;
while(count<n-1)
{
int min=max;
for (int i = 1; i <=n; i++)
{
if (book[i]==0&&dic[i]<min)
{
min=dic[i];j=i;
}
}
book[j]=1;sum+=dic[j];
for (int i = 1; i <=n; i++)
{
if (book[i]==0&&dic[i]>e[j][i])
{
dic[i]=e[j][i];
}
}
count++;
}
cout<<sum;
return 0;
}
ds-工程最短消耗
题目描述
给出一个工程中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<iostream>
#include<string>
#include<queue>
using namespace std;
int loop(int a[20][20],int N)//判断依赖关系是否成立
{
queue<int> q;
int* in = new int[N];
int* visit = new int[N];
for(int i = 0; i < N; i++)
{
in[i] = 0;
visit[i] = 0;
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
if(a[i][j] != -1)
in[j]++;
}
}
for(int i = 0; i < N; i++)
{
if(in[i] == 0)
{
q.push(i);
visit[i] = 1;
break;
}
}
while(!q.empty())
{
int t = q.front();
for(int i = 0; i < N; i++)
{
if(a[t][i] != -1) in[i]--;
}
for(int i = 0; i < N; i++)
{
if(in[i] == 0 && visit[i] == 0)
{
q.push(i);
visit[i] = 1;
}
}
q.pop();
}
for(int i = 0; i < N; i++)
{
if(visit[i] == 0)return -1;
}
return 0;
}
int maxpath(int s, int a[20][20], int N, int* e)
{
int* et = new int[N];
int* flag = new int[N];
for(int i = 0; i < N; i++)
{
et[i] = 0;
flag[i] = 0;
}
queue<int> q;
q.push(s);
while(!q.empty())
{
int t = q.front();
for(int i = 0; i < N; i++)
if(a[t][i] != -1)
{
q.push(i);
et[i] = (et[i] > et[t] + a[t][i]) ? et[i] : et[t] + a[t][i];
flag[t] = 1;//后面的时间已包括该阶段消耗时间;
}
q.pop();
}
for(int i = 0; i < N; i++)
et[i] += e[i];
int max = 0;
for(int i = 0; i < N; i++)
{
if(flag[i] == 0 && et[i] > max)
{
max = et[i];
}
}
return max;
}
int main()
{
int N;
string s;
cin >> N;
getchar();
int a[20][20];
int* e = new int[N];
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
a[i][j] = -1;
}
for(int i = 0; i < N; i++)
{
getline(cin, s);//istream& getline ( istream &is , string &str , char delim );默认的char delim为'\n';
int k = 2;
if(s[k] == ' ') k++;
if((k + 1 < s.length() && s[k + 1] == ' ') || k == s.length() - 1)
{
e[i] = s[k] - '0';//存入活动消耗的时间
k += 2;
}
else
{
e[i] = 10 * (s[k] - '0') + s[k + 1] - '0';
k += 3;
}
while(k + 1 < s.length())
{
if(s[k+1] == ';')
{
a[s[k] - '0' - 1][i] = s[k] - '0' - 1;
k += 2;
}
else
{
a[(s[k] - '0' - 1) * 10 + s[k + 1]- '0' - 1][i] = (s[k] - '0' -1 ) * 10 + s[k + 1] -'0' - 1;
k += 3;
}
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
if(a[i][j] != -1) a[i][j] = e[a[i][j]];
}
}
if(loop(a,N) == -1)
{
cout << "error" << endl;
return 0;
}
else
{
int max = 0;
for(int i = 0; i < N; i++)
{
int flag = 0;
for(int j = 0; j < N; j++)
{
if(a[j][i] != -1)
{
flag = 1;
break;
}
}
if(flag == 0)
{
int t = maxpath(i, a, N, e);
if(t > max)max = t;
}
}
cout << max << endl;
return 0;
}
}
ds-判断排序方法
题目描述
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成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
#include<iostream>
#include<vector>
using namespace std;
class solution
{
public:
int n;
vector<int>arr;
vector<int>temp;
vector<int>insertion;
vector<int>merge;
solution()
{
arr.push_back(0);
temp.push_back(0);
}
bool insertsort()
{
insertion=arr;
bool isinsert=0;
int j=0;
int t;
int next=0;
for (int i=2;i<=n;i++)
{
if (insertion[i]<insertion[i-1])//A[I]小于前驱,插入前面
{
t=insertion[i];//复制为哨兵,防止覆盖
for (j=i-1;t<insertion[j];--j)insertion[j+1]=insertion[j];//从i-1开始往后挪,直到j对应的数比哨兵小,j+1位填上哨兵,排好了
insertion[j+1]=t;}
if (next)
{
break;
}
if (temp==insertion)
{
isinsert=1;next=1;
}
}
return isinsert;
}
bool mergesort()
{
bool ismerge=0;
merge=arr;
int book=0;
vector<int>b=merge;
for (int seg = 1; seg < n; seg += seg) {
for (int start = 1; start <= n; start += seg + seg) {
int low = start, mid = min(start + seg, n+1), high = min(start + seg + seg, n+1);
int k = low;
int start1 = low, end1 = mid;
int start2 = mid, end2 = high;
while (start1 < end1 && start2 < end2)
b[k++] = merge[start1] < merge[start2] ? merge[start1++] : merge[start2++];
while (start1 < end1)
b[k++] = merge[start1++];
while (start2 < end2)
b[k++] = merge[start2++];
}
merge=b;
if (book)
{break;
}
if (merge==temp)
{
ismerge=1;book=1;
}
}
return ismerge;
}
};
int main()
{
solution s;
cin>>s.n;
int temp;
for (int i=1;i<=s.n;i++)
{
cin>>temp;
s.arr.push_back(temp);
}
for (int i=1;i<=s.n;i++)
{
cin>>temp;
s.temp.push_back(temp);
}
if(s.insertsort())
{cout<<"Insertion Sort"<<endl;
for (int i=1;i<s.n;i++)
{
cout<<s.insertion[i]<<" ";
}
cout<<s.insertion[s.n];}
if(s.mergesort())
{cout<<"Merge Sort"<<endl;
for (int i=1;i<s.n;i++)
{
cout<<s.merge[i]<<" ";
}
cout<<s.merge[s.n];}
// system("pause");
return 0;
}
ds-希尔排序的间隔
题目描述
假设输入的序列为希尔排序的中间结果,请输出当前序列的最小间隔。
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<iostream>
#include<vector>
using namespace std;
class solution
{
public:
int n;
vector<int>arr;
solution()
{
arr.push_back(0);
}
int gap()
{
int g=2;
bool isgap=0;
while(g<=n && isgap==0)
{
while (arr[1]>arr[g])g++;
//验证,没问题就带着这个g跳出循环可以得到gap
isgap=1;
for (int i=1;i<g;i++)
{
int c=i;
while (c+g-1<=n)
{
if (arr[c]>arr[c+g-1])
{
isgap=0;
break;
}
c+=(g-1);
}
if (isgap==0)
{
break;
}
}
if (isgap==0)
{
g++;
}
}
return g-1;
}
};
int main()
{
solution s;
cin>>s.n;
int temp;
for (int i=1;i<=s.n;i++)
{
cin>>temp;
s.arr.push_back(temp);
}
cout<<s.gap();
//system("pause");
return 0;
}
ds-快速排序算法
题目描述
使用快速排序算法将n个整数由小到大进行排序。并输出快排的第一趟排序结果以及最终的有序序列。
快速排序选取完pivot之后的进行整理的实现方法有很多,其中一种为”(前后指针法)“根据下面的描述进行实现并按要求输出,
以排序序列的最后一个值作为标准值pivot。
交换法:
选取最后一个关键字( pivot )作为枢轴。
设置两个变量left = 0;right = N - 2;
从left一直向后走,直到找到一个大于等于 pivot 的值,right从后至前,直至找到一个小于 pivot 的值,然后交换这两个数。
重复第三步,一直往后找,直到left和right相遇,然后将 pivot 放置合适位置即可
输入:
n表示输入序列的长度,后边为n个要排序的整数序列,以空格分隔;
输出:
第一趟排序结果,以空格分隔,行尾无空格;
最终的有序序列结果,以空格分隔,行尾无空格;
样例输入输出
样例1
输入:
10 4 1 7 6 9 2 8 0 3 5
输出:
4 1 3 0 2 5 8 6 7 9
0 1 2 3 4 5 6 7 8 9
样例2
输入:
10 9 1 3 8 23 5 7 10 29 19
输出:
9 1 3 8 10 5 7 19 29 23
1 3 5 7 8 9 10 19 23 29
#include<iostream>
#include<vector>
using namespace std;
class solution
{
public:
int n;
vector<int>input;
int count;
solution(){count=0;}
void quicksort(int left, int right)
{
int i = left, j = right ;
if (left > right) return;
while (i != j)
{
while (input[i] <= input[right] && i < j)i++;
while (input[j] >= input[right] && i < j)j--;
if (i < j)
{
int t = input[i];
input[i] = input[j];
input[j] = t;
}
}
int s = input[right];
input[right] = input[i];
input[i] = s;
count++;
if (count == 1)
{
for (int i = 1; i < n; i++)
{
cout << input[i] << " ";
}
cout << input[n] << endl;
}
quicksort(i + 1, right);
quicksort(left, i - 1);
return;
}
};
int main()
{
solution s;
cin >> s.n;
s.input.push_back(1);
for (int i = 1; i <= s.n; i++)
{
int x;
cin >> x;
s.input.push_back(x);
}
s.quicksort(1, s.n);
for (int i = 1; i < s.n; i++)
{
cout << s.input[i] << " ";
}
cout << s.input[s.n] << endl;
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<iostream>
#include<vector>
using namespace std;
int main()
{
int row1,row2,column1,column2,count1,count2;
cin>>row1>>column1>>count1;
int **ju1=new int*[row1+1];
for (int i = 0; i <= row1; i++)
{
ju1[i]=new int[column1+1]{0};
}
int x,y,val;
for (int i = 0; i < count1; i++)
{
cin>>x>>y>>val;
ju1[x][y]=val;ju1[x][0]=1;
}
//cin.get();
cin>>column2>>row2>>count2;
if (row1!=row2||column1!=column2)
{
for (int i = 0; i <= row1; i++)
{
delete[]ju1[i];
}
delete[]ju1;
cout<<"ERROR"<<endl;
//system("pause");
return 0;
}
int **ju2=new int*[row2+1];
for (int i = 0; i <= row2; i++)
{
ju2[i]=new int[column2+1]{0};
}
for (int i = 0; i < count2; i++)
{
cin>>y>>x>>val;
ju2[x][y]=val;ju2[x][0]=1;
}
vector <int>row;
vector<int>column;
vector<int>value;
for (int i = 1; i <= row1; i++)
{
for (int j = 0; j <= row2; j++)
{
if (ju1[i][0]==1&&ju2[j][0]==1)
{
int sum=0;
for (int k = 1; k <= column1; k++)
{
sum+=ju1[i][k]*ju2[j][k];
}
if (sum!=0)
{
row.push_back(i);
column.push_back(j);
value.push_back(sum);
}
}
}
}
if (row.empty())
{
cout<<"The answer is a Zero Matrix"<<endl;
}
else
{
for (int i = 0; i < row.size(); i++)
{
cout<<row[i]<<" "<<column[i]<<" "<<value[i]<<endl;
}
}
for (int i = 0; i <= row1; i++)
{
delete[]ju1[i];
}
delete[]ju1;
for (int i = 0; i <= row2; i++)
{
delete[]ju2[i];
}
delete[]ju2;
//system("pause");
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
从1开始
#include <iostream>
#include <string>
using namespace std;
void getnext(string t,int next[])
{
next[1]=0;
int i=1,j=0;
while(i<t.length()-1)
{
if (j==0||t[i]==t[j])
{
++i;++j;
next[i]=j;
}
else
{
j=next[j];
}
}
//优化
for (i=2;i<t.length();i++)
{
if (t[i]==t[next[i]])
{
next[i]==next[next[i]];
}
}
}
void kmp(string s,string t)
{
int*next=new int [t.length()];
int i=1,j=1;
getnext(t,next);
while (i<s.length()&&j<t.length())
{
if (j==0||s[i]==t[j])
{
++i;++j;
}
else
{
j=next[j];
}
}
if (j>=t.length())
{
cout<<i-t.length();
}
else
{
cout<<"no";
}
}
int main()
{
string s,t;
cin>>s>>t;
kmp(" "+s," "+t);
getchar();getchar();
return 0;
}
从0开始
#include <iostream>
#include <string>
using namespace std;
void getnext(string t,int next[])
{
next[0]=-1;
int i=0,j=-1;
while(i<t.length()-1)
{
if (j==-1||t[i]==t[j])
{
++i;++j;
next[i]=j;
}
else
{
j=next[j];
}
}
for (int m=2;m<t.length();m++)
{
if (t[m]==t[next[m]])
{
next[m]=next[next[m]];
}
}
}
void kmp(string s,string t)
{
int *next=new int[t.length()];
getnext(t,next);
int i=0,j=0;
//这里出现-1大于 .length() or .size() 的情况是因为-1变成无符号是补码全为1超级大
//因为string的size类型是size_t,一般是32位或者64位无符号整数;而-1是int类型,
//在与unsigned int(也可能是unsigned long等等,看你具体编译器)进行比较时会被提升为相应的无符号类型,而-1的二进制补码是全1,
//把全1的二进制码当做无符号数解释的时候是无符号数的最大值,所以-1是最大的。
while (i<s.length()&&j<signed(t.length()))
{
if (j==-1||s[i]==t[j])
{
++i;++j;
}
else
{
j=next[j];
}
}
if (j>=signed(t.length()))
{
cout<< i-t.length();
delete []next;
}
else
{
cout<<"no";
delete []next;
}
}
int main()
{
string s,t;
cin>>s;
cin>>t;
kmp(s,t);
return 0;
}
哈夫曼树A
题目描述
根据输入的信息,构建哈夫曼树,要求构造树时,频次低的节点在左,频次高的节点在右。并按照深度优先的中根遍历输出字符编码。
输入:先输入需要编码的字符个数,然后按顺序输入编码字符(单char字符)及该字符出现频次。
输出:按深度优先的中根遍历顺序输出编码字符及其编码,字符及编码中间用冒号隔开。
附件
样例输入输出
样例1
输入:
6
a 267
b 96
c 730
d 787
e 10
f 610
输出:
e:0000
b:0001
a:001
f:01
c:10
d:11
#include <iostream>
#include<algorithm>
using namespace std;
#include <vector>
#include <stack>
struct TreeNode
{
int wei;
char val;
TreeNode*p,*l,*r;
TreeNode(int w,TreeNode* l,TreeNode* r)
:wei(w),p(nullptr),l(l),r(r)
{
l->p=this;
r->p=this;
}
TreeNode(int w,char v):val(v),wei(w),p(nullptr),l(nullptr),r(nullptr){}
/*bool operator <(TreeNode*& node) //因为要用sort()进行排序,重载运算符'<'
{
return wei<node->wei;
}
*/
};
bool greasy(TreeNode* a, TreeNode* b)
{
return (a->wei<b->wei);
}
class solution
{
public:
int n;
vector<TreeNode*>node;
TreeNode* hafutree;
void buildhf()
{
if (node.size()<1)
{
return ;
}
sort(node.begin(),node.end(),greasy);
while (node.size()>1)
{combine();
}
inorder(hafutree);
}
stack<int>bian;
void inorder(TreeNode* root)
{
if (!root){return ;}
bian.push(0);
inorder(root->l);
bian.pop();
if(!root->l&&!root->r)
{
cout<<root->val<<":";
stack<int>x;
stack<int>b=bian;
while (!b.empty())
{
x.push(b.top());
b.pop();
}
while (!x.empty())
{
cout<<x.top();
x.pop();
}
cout<<endl;
}
bian.push(1);
inorder(root->r);
bian.pop();
}
void combine()
{
hafutree=new TreeNode((node[0]->wei+node
[1]->wei),node[0],node[1]);
node.erase(node.begin());
node.erase(node.begin());
node.push_back(hafutree);
sort(node.begin(),node.end(),greasy);
}
};
int main()
{
solution s;
cin>>s.n;
char v;
int w;
if (s.n==1)
{
cin>>v>>w;
cout<<v<<":"<<1<<endl;
//system("pause");
return 0;
}
for (int i=0;i<s.n;i++)
{
cin>>v>>w;
TreeNode * node=new TreeNode(w,v);
s.node.push_back(node);
}
s.buildhf();
//system("pause");
return 0;
}