Dating
思路:这个题目中的公共字符相对简单的,它们的下标是一致的,所以直接同步遍历即可。
//
// @author prime on 2017/6/29.
//
#include
using namespace std;
int main()
{
string a,b,c,d;
cin>>a>>b>>c>>d;
auto len1=min(a.size(),b.size());
auto len2=min(c.size(),d.size());
int res[3];
int next;
for (int i=0;iif(a[i]==b[i]&&a[i]>='A'&&a[i]<='G')
{
res[0]=a[i]-'A';//一周内的第几天(0~6)
next=i;
break;
}
}
for (int i=next+1;iif(a[i]==b[i]&&(a[i]>='0'&&a[i]<='9'||a[i]>='A'&&a[i]<='N'))
{
if(a[i]>='0'&&a[i]<='9')
res[1]=a[i]-'0';//几点
else
res[1]=a[i]-'A'+10;
break;
}
for (int i=0;iif(c[i]==d[i]&&(c[i]>='A'&&c[i]<='Z'||c[i]>='a'&&c[i]<='z'))
{
res[2]=i;
break;
}
}
string week[]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
cout<0]]<<" ";
printf("%02d:%02d",res[1],res[2]);//日期格式,各占2位
return 0;
}
Talent and Virtue
思路:经典套路,一遍过,不多说了。
//
// @author prime on 2017/6/29.
//
#include
#include
#include
using namespace std;
struct People
{
int talent,virtue;
int id;
};
bool cmp(const People&o1,const People&o2)
{
if((o1.virtue+o1.talent)!=(o2.virtue+o2.talent))
return (o1.virtue+o1.talent)>(o2.virtue+o2.talent);
else
{
if(o1.virtue!=o2.virtue)
return o1.virtue>o2.virtue;
else
return o1.idint main()
{
int N,L,H;
scanf("%d%d%d",&N,&L,&H);
vector sage,nobleman,foolman,smallman;
for (int i=0;iscanf("%d%d%d",&tmp.id,&tmp.virtue,&tmp.talent);
if(tmp.talentcontinue;
else if(tmp.virtue>=H&&tmp.talent>=H)
sage.push_back(tmp);
else if(tmp.virtue>=H&&tmp.talentelse if(tmp.virtue>=tmp.talent)
foolman.push_back(tmp);
else if(tmp.talent>tmp.virtue)
smallman.push_back(tmp);
}
sort(sage.begin(),sage.end(),cmp);
sort(nobleman.begin(),nobleman.end(),cmp);
sort(foolman.begin(),foolman.end(),cmp);
sort(smallman.begin(),smallman.end(),cmp);
printf("%lld\n",sage.size()+nobleman.size()+foolman.size()+smallman.size());
for (auto &e:sage)
printf("%08d %d %d\n",e.id,e.virtue,e.talent);
for (auto &e:nobleman)
printf("%08d %d %d\n",e.id,e.virtue,e.talent);
for (auto &e:foolman)
printf("%08d %d %d\n",e.id,e.virtue,e.talent);
for (auto &e:smallman)
printf("%08d %d %d\n",e.id,e.virtue,e.talent);
return 0;
}
Set Similarity
思路:直接把两个序列都放入集合中,题目中序列可能有重复,这就不用管了。然后遍历其中一个集合,不在另一个集合中的元素就nt++,否则nc++,这里nt就是并集,nc就是交集,所以一开始nc为0,nt为另一个集合大小。
//
// @author prime on 2017/6/29.
//
#include
#include
#include
using namespace std;
int main()
{
int N;
scanf("%d",&N);
vector<unordered_set<int>> arr;
for (int i=0;iint M;
scanf("%d",&M);
unordered_set<int> s;
for (int j=0,tmp;jscanf("%d",&tmp);
s.insert(tmp);
}
arr.push_back(s);
}
int K;
scanf("%d",&K);
for (int i=0;iint a,b;
scanf("%d%d",&a,&b);
int nc=0,nt=arr[b-1].size();
for (auto&e:arr[a-1])
{
if(arr[b-1].find(e)==arr[b-1].end())
nt++;
else
nc++;
}
printf("%0.1f%\n",(100.0*nc)/nt);
}
return 0;
}
Complete Binary Search Tree
给你一个序列,构造一个完全BST树,输出其层序遍历的结果。
思路:和1020思路相近,这里给出了一个序列,那么只要把它们从小到大排序即是中序序列了。这道题就变成了给出中序序列求出其层序序列。补充一下,n个结点的二叉树高度是 logn2+1
算法完全可以沿用1020的,只不过需要单独确定根节点的位置。也就是说,要计算左子树总共有几个结点,然后用start+结点数就是根节点的位置。
//
// @author prime on 2017/6/30.
//
#include
#include
#include
using namespace std;
int tree[20000];
void pre_traversal(const vector<int>& in_order,int start,int end,int index)
{//index和以前一样,start是中序起点,end是中序的终点。
if(start>end)
return;
int n = end - start + 1;//这棵子树一共n个结点
int L=log(n)/log(2);//除去叶子层,一共有几层
int num=n-(pow(2,L)-1);//叶子结点个数
int root=start+(pow(2,L-1)-1)+min((double)num,pow(2,L-1));//根的左子树的最后一层可能满了也可能没满,所以需要用min确定到底有几个结点
tree[index]=in_order[root];
pre_traversal(in_order,start,root-1,2*index);
pre_traversal(in_order,root+1,end,2*index+1);
}
int main()
{
int N;
scanf("%d",&N);
fill(tree,tree+20000,-1);
vector<int> in_order(N);
for (int i=0;iscanf("%d",&in_order[i]);
sort(in_order.begin(),in_order.end());
pre_traversal(in_order,0,N-1,1);
int count=0;
for (auto&e:tree)
{
if(e!=-1)
{
if(count==N-1)
printf("%d",e);
else
printf("%d ",e);
count++;
}
if(count==N)
break;
}
return 0;
}
A+B and C (64bit)
给定abc判断是否a+b>c
思路:题目中说了abc本身不会溢出,但是相加可能会,所以不要用字符串存储它们了,直接根据溢出判断,比如a>0 b>0,a+b<=0了,毫无疑问,溢出了,a+b肯定比c大了。。
//
// @author prime on 2017/6/30.
//
#include
using namespace std;
int main()
{
int T;
scanf("%d",&T);
long long a,b,c,sum;
for (int i=0;iscanf("%lld %lld %lld",&a,&b,&c);
sum=a+b;
printf("Case #%d: ",i+1);
if(a>0&&b>0)
{
if(sum>0&&sum<=c)
printf("false\n");
else
printf("true\n");
} else if(a<0&&b<0)
{
if(sum<0&&sum>c)
printf("true\n");
else
printf("false\n");
} else
{
if(sum<=c)
printf("false\n");
else
printf("true\n");
}
}
return 0;
}
Root of AVL Tree
非常经典的AVL树的题目,多看看!
思路:下面一张图就是思路,Wikipedia太好了,可以彻底放弃百度了。
//
// @author prime on 2017/6/30.
//
#include
using namespace std;
struct Node
{
int val;
Node *left,*right;
};
Node* Right_Rotation(Node*root)
{
Node*pivot=root->left;
root->left=pivot->right;
pivot->right=root;
return pivot;
}
Node* Left_Rotation(Node*root)
{
Node*pivot=root->right;
root->right=pivot->left;
pivot->left=root;
return pivot;
}
Node* Left_Right_Rotation(Node* root)
{
root->left=Left_Rotation(root->left);
return Right_Rotation(root);
}
Node* Right_Left_Rotation(Node* root)
{
root->right=Right_Rotation(root->right);
return Left_Rotation(root);
}
int getHeight(Node*root)
{
if(root== nullptr)
return 0;
else
return max(getHeight(root->left),getHeight(root->right))+1;
}
Node* insert(Node*root,int val)
{
if(root== nullptr)
{
root=new Node;
root->val=val;
root->left=root->right= nullptr;
}
else if(valval)
{//插入左子树
root->left=insert(root->left,val);
if(getHeight(root->left)-getHeight(root->right)==2)
root=valleft->val?Right_Rotation(root):Left_Right_Rotation(root);
}
else
{//插入右子树
root->right=insert(root->right,val);
if(getHeight(root->left)-getHeight(root->right)==-2)
root=valright->val?Right_Left_Rotation(root):Left_Rotation(root);
}
return root;
}
void pre_order(Node*root)
{//debug用的,可以删除
if(root== nullptr)
return;
else
{
printf("%d ",root->val);
pre_order(root->left);
pre_order(root->right);
}
}
int main()
{
int N;
scanf("%d",&N);
Node* root= nullptr;
for (int i=0;iint val;
scanf("%d",&val);
root=insert(root,val);
}
//pre_order(root);
printf("%d",root->val);
return 0;
}
Sort with Swap(0,*)
每次只能用0与其它数交换,最少几次让其有序?(从小到大)
思路:输入的数都在[0,n-1]之间,每次用0交换时分两种情况:0的下标就是0,此时0和第一个不在其位的数交换;否则 ,0和0所在位置的数交换位置。因为需要频繁查询位置,所以对输入的数建立一个数——>下标的映射关系,交换也是对它进行。其中,index指向第一个不在其位置上的数的下标,每次0在其位时,就和index交换,index是递增的,每次都能把index归位,利用index可以不用每次都遍历查找了。
//
// @author prime on 2017/7/1.
//
#include
#include
using namespace std;
int main()
{
int N;
scanf("%d",&N);
vector<int> pos(N);
int total=0;//统计除了0有多少个数不在其位
for (int i=0,a;iscanf("%d",&a);
pos[a]=i;
if(a!=i&&a!=0)
total++;
}
int index=1;//第一个不在原本位置上的数的下标
int res=0;//需要交换的总次数
while(total!=0)
{
if(pos[0]!=0)
{//0在i位上,就把0和i的位置对换,这样i归位
swap(pos[0],pos[pos[0]]);
res++;
total--;
}
else
{
for (;indexif(pos[index]!=index)
break;
}
swap(pos[index],pos[0]);
res++;
}
}
printf("%d",res);
return 0;
}
Find More Coins
思路:“见规死”的神话能不能破。。/(ㄒoㄒ)/~~。表面上子集求和,挺难得,不会。但是转换思路,可以把总金额变成背包容量,货币面值变成物品,其价值和重量相等。那么,就转换成0-1背包问题了。
由于需要打印具体货币,所以用了个二维数组保存过程。先把货币从大到小排序,这样最后构造解的时候才符合题意。
//
// @author prime on 2017/7/1.
//
#include
#include
#include
using namespace std;
int main()
{
int N,M;
scanf("%d%d",&N,&M);
vector<int> w(N);
for (int i=0;iscanf("%d",&w[i]);
int dp[N+1][M+1];//dp[i][j]从前i个商品中总重量不超过j的最大价值
bool choice[N+1][M+1];//记录选择
fill(choice[0],choice[0]+(N+1)*(M+1),false);
fill(dp[0],dp[0]+M+1,0);
sort(w.begin(),w.end(),greater<int>());
for (int i=0;ifor (int j=0;j<=M;j++)
{
if(j1][j]=dp[i][j];
else
{
if(dp[i][j]>dp[i][j-w[i]]+w[i])
{
dp[i+1][j]=dp[i][j];
}
else
{
dp[i+1][j]=dp[i][j-w[i]]+w[i];
choice[i][j]=true;
}
}
}
if(dp[N][M]!=M)
printf("No Solution");
else
{
vector<int> res;
int total=M,index=N;
while(total!=0)
{
if(choice[index][total])
{
res.push_back(w[index]);
total-=w[index];
}
index--;
}
for (int i=0;iprintf("%d",res[i]);
if(i!=res.size()-1)
printf(" ");
}
}
return 0;
}
The Black Hole of Numbers
需要注意输入可能为6174,此时也要按过程走一波。所以得用do-while
//
// @author prime on 2017/7/1.
//
#include
#include
using namespace std;
void process(string num)
{
string a,b;
int ia,ib;
num.insert(0,4-num.size(),'0');
do
{
sort(num.begin(),num.end(),greater<char>());
a=num;
sort(num.begin(),num.end(),less<char>());
b=num;
if(a==b)
{
cout<" - "<" = 0000";
break;
}
ia=stoi(a);
ib=stoi(b);
num=to_string(ia-ib);
num.insert(0,4-num.size(),'0');
cout<" - "<" = "<while(num!="6174");
}
int main()
{
string num,a,b;
cin>>num;
process(num);
return 0;
}
Mooncake
思路:按最高利润排序即可,优先卖高利润的月饼,没毛病。
//
// @author prime on 2017/7/1.
//
#include
#include
#include
using namespace std;
struct Mooncake
{
double inventory;
double price;
double rate;//性价比
};
bool cmp(const Mooncake&o1,const Mooncake&o2)
{
return o1.rate>o2.rate;
}
int main()
{
int N,D;
scanf("%d%d",&N,&D);
vector s(N);
for (int i=0;iscanf("%lf",&s[i].inventory);
}
for (int i=0;iscanf("%lf",&s[i].price);
s[i].rate=s[i].price/s[i].inventory;
}
sort(s.begin(),s.end(),cmp);
double total_profit=0;
for (int i=0;iif(s[i].inventory>D)
{
total_profit+=D*s[i].rate;
break;
}
else
{
D-=s[i].inventory;
total_profit+=s[i].price;
}
}
printf("%.2lf",total_profit);
return 0;
}