给女朋友的题解专栏
括号匹配
/* 由题意可知这个题我们只关注三种括号即可 如果字符串是这样的{}((SK* )()),那么可以去掉其他字符变成这样——{}(()()) 为了方便描述,每个字符的对应位置如下 0 1 2 3 4 5 6 7 { } ( ( ) ( ) ) 那么模拟一下代码流程,一共有八个字符,将分成八个步骤来讲解。 0、我们首先遇到的是'{’ 此时栈当中没有元素,可知左括号是无法与其他括号匹配的,所以将‘{’塞入栈当中,此时栈的元素有一个——‘{’,此时栈的内容是这样的【‘{’】。 1、第二个字符为‘}’, 我们可以知道的是右括号可以与左括号匹配,而字符'}'可以匹配的字符是'{'。此时可以看到的是栈尾元素是'{',那么这两个括号是可以匹配的,就像消消乐一样,我们可以将其消除掉,此时栈的内容是这样的【】,什么都没有 2、遇到括号'(',与0步骤一样,将其填入栈中,栈内容是这样的【'('】 3、同上,栈内容为【'(','('】 4、遇到括号')',可以看到栈尾元素为'(',消除,栈内容变为【'('】 5、同步骤2,栈内容变为【'(','('】 6、遇到')',栈尾元素为‘(',消除,栈内容变为【'('】 7、遇到')',栈尾元素为‘(',消除,栈内容变为【】 最后我们可以看到栈内容为空,说明所有括号都匹配上了,输出yes */ #include<iostream> #include<stdio.h> using namespace std; int main(){ cout<<(0x70)<<endl; char str[1050]; while(gets(str)){ char stack[1004]; int num = 0; for (int i = 0; str[i]; i++){ if(str[i] == ')'){ //当前元素为’)' if(num > 0 && stack[num-1] == '('){//栈不为空,并且栈尾元素为'(' num --; //可以匹配,将栈尾元素消除 }else stack[num ++] = str[i];//否则说明无法匹配,将此字符压入栈中 } if(str[i] == ']'){ //当前元素为’]' if(num > 0 && stack[num-1] == '['){//栈不为空,并且栈尾元素为'[' num --; //可以匹配,将栈尾元素消除 }else stack[num ++] = str[i];//否则说明无法匹配,将此字符压入栈中 } if(str[i] == '}'){ //思路同上 if(num > 0 && stack[num-1] == '{'){ num --; }else stack[num ++] = str[i]; } if(str[i] == '(' || str[i] == '[' || str[i] == '{'){//遇到左括号则直接将其压入栈中 stack[num ++] = str[i]; } } if(num == 0){ //栈的内容为空,说明所有括号都已经匹配上了 printf("yes\n"); }else { //栈内容不为空,说明右括号没有匹配到 printf("no\n"); } } }
链表插入删除
#include<stdio.h> #include<stdlib.h> typedef struct node{ int data; struct node *next; }Node,*LinkList; /*创建一个新链表*/ void CreatList_L(LinkList &L,int n) { int a; L = (LinkList)malloc(sizeof(Node)); L->next = NULL;//建立一个带头结点的单链表 Node *q = L; for(int i=0;i<n;i++) { Node *p = (LinkList)malloc(sizeof(Node)); scanf("%d",&a); p->data = a; q->next = p; p->next=NULL; q = q->next; } } /*在链表的第i处插入一个元素*/ void Push_L(LinkList &L, int data, int i) { Node *p = L; int j = 1; while(p&&j<i) { p=p->next; ++j; } Node *q = (LinkList)malloc(sizeof(Node)); q->data = data; q->next = p->next; p->next = q; } /*删除第i个元素*/ void Delete_L(LinkList &L,int i) { Node *p = L; if(i<0) printf("INFEASIBLE"); int j = 1; while(p&&j<i) { p=p->next; ++j; } Node *q = p->next; p->next = p->next->next; free(q); } void Traverse_L(LinkList &L) { LinkList p = L->next; while(p!=NULL){ printf("%d ",p->data); p = p->next; } printf("\n"); }//正序遍历整个链表 int main() { LinkList L; int n; printf("输入要创建的链表中的元素个数:\n"); scanf("%d",&n); printf("输入%d个元素:\n",n); CreatList_L(L,n); printf("遍历整个链表\n"); Traverse_L(L); int push_data,push_i; printf("输入你想要插入的元素和它的插入位置:\n"); { scanf("%d%d",&push_data,&push_i); } Push_L(L, push_data, push_i); printf("插入后的链表遍历为:\n"); Traverse_L(L); int del_i; printf("输入要删除链表中的第几个元素:\n"); scanf("%d", &del_i); Delete_L(L, del_i); printf("删除后的链表遍历为:\n"); Traverse_L(L); return 0; }
进制转换
//进制转换 #include<stdio.h> #include<stdlib.h> #define MAX_SIZE 80 typedef struct { //栈的数据结构,采用数组 char data[MAX_SIZE]; int top; } stack; int isfull(stack s) { //判断栈是否已满 return (++s.top==MAX_SIZE); } int isempty(stack s) { //判断栈为空 return s.top==-1; } void push(stack * s,char in_data) { //进栈 if(isfull(*s)) { printf("栈已满,不能执行操作!\n"); exit(1); } s->data[++s->top]=in_data; } void pop(stack *s) { //出栈 if(isempty(*s)) { printf("栈已空,不能执行操作!\n"); exit(1); } s->top--; } char top_value(stack *s) { //取栈顶元素 if(isempty(*s)) { printf("栈已空,不能执行操作!\n"); exit(1); } return s->data[s->top]; } int main(int argc,char** argv) { int number; stack result; result.top=-1; int r_range; printf("输入转换的数据和对应的进制:"); scanf("%d%d",&number,&r_range); printf("%d对应的%d进制为:",number,r_range); while(number!=0) { char input; if(number%r_range>=10) input=((number%r_range)-10)+'a'; else input=((number%r_range)+'0'); push(&result,input); number=number/r_range; } while(!isempty(result)) { putchar(top_value(&result)); pop(&result); } return 0; }
顺序表操作
//这道题是考验顺序表操作的基础题 //每次遍历到一个元素,我们就可以找一下这个元素在之前出没出现过,如果出现过,就可以删除。 #include<iostream> #include<stdio.h> #include<string.h> using namespace std; int main(){ int num1[2005]; int num2[2005]; int n1 = 0; while(cin >> n1){ //输入数组长度 int n2 = 0; for(int i = 0; i < n1; i++){ //输出元素 cin>>num1[i]; } for(int i = 0 ; i< n1; i++){ //遍历数组 bool exist = false; //这个值表示此元素在之前出没出现过,false为没出现过。 for(int k = 0; k < i; k++){ //遍历之前的元素 if(num1[i] == num1[k]){ //相等表示出现过 exist = true; //将exist置为true,表示此元素在之前出现过 } } if(exist == false){ //如果此元素在之前没有出现过,那么将其塞入num2顺序表中。 num2[n2++] = num1[i]; } } cout<<n2<<endl; //输出num2顺序表的长度 for(int i = 0; i < n2; i++){ //输出num2顺序表 cout << num2[i]; if(i != n2 - 1){ cout<<" "; } }cout<<endl; } }
约瑟夫环
/* 题目描述 n个人想玩残酷的死亡游戏,游戏规则如下: n个人进行编号,分别从1到n,排成一个圈,顺时针从1开始数到m,数到m的人被杀,剩下的人继续游戏,活到最后的一个人是胜利者。 请输出最后一个人的编号。 输入 输入n和m值。 输出 输出胜利者的编号。 */ //经典的约瑟夫环问题,我们可以用链表来实现它。 //从第一个数开始查,每到m的倍数就可以将此人删掉 #include <stdio.h> #include <stdlib.h> #include<iostream> using namespace std; class node { public: int data; node *next; }; int main() { int n,m,w; while(cin>>n>>m){ //输入n个人,每m个退出一人 int i; node *head,*p,*tail,*q; head=new node; //链表头 head->next=NULL; //初始化链表头,第一个人编号十一 head->data=1; tail=head; //rail表示链表的尾部 for(i=2;i<=n;i++) //依次插入2,3,4,5。。。。 { p=new node; //新建一个节点 p->data=i; //i表示此人的编号,初始化此节点 p->next=NULL; tail->next=p; //将链表尾部的指针指向此节点 tail=p; //现在链表的尾部变成了此节点(第i个人的节点) } tail->next=head; //将尾部的指针指向头部,这样形成了一个环 q=head; while(q->next!=q)//从头开始遍历链表,当q的下一个节点等于q的时候,说明只有q一个元素了,退出循环 { for(i=1;i<m-1;i++) //遍历到第m-1个节点,下一个节点就是我们要删除的节点 { q=q->next; } q->next=q->next->next; //删除q->next这个节点 q=q->next; //下次遍历从新的q这个节点开始遍历 } printf("%d\n",q->data); //输出结果 } return 0; } /* 题目描述 n个人想玩残酷的死亡游戏,游戏规则如下: n个人进行编号,分别从1到n,排成一个圈,顺时针从1开始数到m,数到m的人被杀,剩下的人继续游戏,活到最后的一个人是胜利者。 请输出最后一个人的编号。 输入 输入n和m值。 输出 输出胜利者的编号。 */ //经典的约瑟夫环问题,我们可以用链表来实现它。 //从第一个数开始查,每到m的倍数就可以将此人删掉 #include <stdio.h> #include <stdlib.h> #include<iostream> using namespace std; class node { public: int data; node *next; }; int main() { int n,m,w; while(cin>>n>>m){ //输入n个人,每m个退出一人 int i; node *head,*p,*tail,*q; head=new node; //链表头 head->next=NULL; //初始化链表头,第一个人编号十一 head->data=1; tail=head; //rail表示链表的尾部 for(i=2;i<=n;i++) //依次插入2,3,4,5。。。。 { p=new node; //新建一个节点 p->data=i; //i表示此人的编号,初始化此节点 p->next=NULL; tail->next=p; //将链表尾部的指针指向此节点 tail=p; //现在链表的尾部变成了此节点(第i个人的节点) } tail->next=head; //将尾部的指针指向头部,这样形成了一个环 q=head; while(q->next!=q)//从头开始遍历链表,当q的下一个节点等于q的时候,说明只有q一个元素了,退出循环 { for(i=1;i<m-1;i++) //遍历到第m-1个节点,下一个节点就是我们要删除的节点 { q=q->next; } q->next=q->next->next; //删除q->next这个节点 q=q->next; //下次遍历从新的q这个节点开始遍历 } printf("%d\n",q->data); //输出结果 } return 0; }
大数相加
//首先输入两个字符串。假如分别为12345和23456 //首先将这两个字符串倒过来,分别变成54321和65432 //现在,新的字符循环从前到后分别是个位,十位,百位。。。。 //首先将两个字符串的第0个位置相加,可知5+6为11,那么也就是说,相加之后的数字个位是1,进位为1 //之后将十位相加,可知4+5=9,而个位有一个进位,加上进位之后为10,可知相加数字的十位为0,进位为1,依此类推 #include <string.h> #include<iostream> #include<stdio.h> using namespace std; const int AX = 1e5+666; const int maxn = 1e4+666; char s1[maxn]; char s2[maxn]; int a[maxn]; int b[maxn]; int c[maxn]; int main(){ int T; cin>>T; while(T--){ scanf("%s%s",s1,s2);//输入两个数,以字符串的形式 int len1 = strlen(s1);//计算第一个数的长度 int len2 = strlen(s2);//计算第一个数的长度 memset(a,0,sizeof(a));//清空a数组 memset(b,0,sizeof(b));//清空b数组 memset(c,0,sizeof(c));//清空c数组,存的是相加的结果 for(int i=len1-1;i>=0;i--){//将字符串倒过来,比如原来是12345,现在就变成54321 a[len1-i-1] = s1[i]-'0';//第0个位置存个位,第一个位置存十位,第二个位置存百位。。。。。 } for(int i=len2-1;i>=0;i--){//同上,将第二个数字倒过来 b[len2-i-1] = s2[i]-'0'; } int i,up; int k = max(len1,len2);//计算两个字符串的最大长度 for(i=0,up=0;i<k;i++){//从低位到高位,up是进位 c[i] = a[i] + b[i] + up;//计算当前位相加的结果,要加上进位,之后结果比如是13,那么当前位就是3,进位为1 up = c[i]/10;//计算进位 c[i]%=10;//计算当前 } if(up) c[k] += up;//如果最后发现进位是1,那么说明出现a了例如500+600这种情况,进位为最高位 for(int i=k;i>=0;i--){//倒着将结果字符串输出, if(i==k && c[k] == 0) continue;//如果最高位是零,那么不输出最高位 cout<<c[i]; } cout<<endl; } return 0; }