每日一题,持续更新!
题目来源:PIPIOJ
7月9日
- 题目描述: PIPI给你一个合法的括号序列,希望跟你按左括号下标递增顺序给出每对括号在序列中的下标。(下标从1开始)
- 输入: 多组数据,请处理到EOF。对于每组数据,第一行包括一个只包含’(’,’)'的字符串,保证输入的括号匹配序列合法,长度不超过100000
- 输出: 按左括号下标递增顺序给出每对括号在序列中的下标。
- 样例输入: (())()()
- 样例输出:
1 4
2 3
5 6
7 8
思考:显然是需要用到栈的知识,遇到左括号入栈,遇到右括号,栈里面的左括号出栈匹配。
#include
using namespace std;
//定义栈
#define MAXSIZE 100100
typedef struct Stack{
int data[MAXSIZE];
int top = -1;
}Stack;
int main(){
Stack s;//声明一个栈
int index[MAXSIZE];
char k[MAXSIZE];
while (scanf("%s",&k)!=EOF){
int l = strlen(k);//计算字符串的长度
for (int i = 0; i < l; ++i){
if (k[i] == '('){ //遇到左括号,下标入栈
s.data[++s.top]= i+1;
} else { //遇到右括号,出栈,记录下标
int j = s.data[s.top--];//匹配左括号的下标
index[j] = i+1;
}
}
for (int i = 0; i < l; ++i){
if (index[i] !=0){
printf("%d %d\n",i,index[i]);
index[i] = 0;
}
}
}
return 0;
}
7月10日
- 题目描述
从顺序表L中删除具有最小值的元素(假设唯一)并友函数返回被删元素的值。空出的元素由最后一个元素填补。- 输入
输入包含一个整数n代表顺序表L长度。
接下来包含n个整数,代表顺序表L中的元素。- 输出
若顺序表为空,输出 “error”.
若不为空,输出最小元素的值并输出删除最小值之后的顺序表。- 样例输入
3
1 2 3- 样例输出
1
3 2
#include
using namespace std;
//定义顺序表
typedef struct SqList{
int *data;
int length;
}SqList;
int main(){
SqList s;
int min = 0;
scanf("%d",&s.length);
if (s.length <= 0){
printf("error\n");
return 0;
}
s.data = (int *)malloc(sizeof(int)*s.length);
for (int i = 0; i < s.length; ++i){
scanf("%d",&s.data[i]);
if (s.data[i] < s.data[min]){
min = i;
}
}
int m = s.data[min];
s.data[min] = s.data[s.length-1];
s.length--;
printf("%d\n",m);
for (int i = 0; i < s.length; ++i){
printf("%d ",s.data[i]);
}
printf("\n");
return 0;
}
- 题目描述
PIPI现在由一个顺序表L,他想把顺序表所有元素逆置,要求除了存储L的空间外,辅助的空间复杂度为O(1).- 输入
输入包含一个整数n代表顺序表L长度。
接下来包含n个整数,代表顺序表L中的元素。- 输出
输出逆置后的顺序表- 样例输入
3
1 2 3- 样例输出
3 2 1
#include
using namespace std;
typedef struct SqList{
int *data;
int length;
}SqList;
int main(){
SqList s;
scanf("%d",&s.length);
s.data = (int *) malloc(sizeof(int)*s.length);
for (int i = 0; i < s.length; ++i){
scanf("%d",&s.data[i]);
}
//逆置
int l=0,r=s.length-1;
int temp;
while (r>l){
temp = s.data[l];
s.data[l] = s.data[r];
s.data[r] = temp;
l++;
r--;
}
for (int i = 0; i < s.length; ++i){
printf("%d ",s.data[i]);
}
printf("\n");
free(s.data);
return 0;
}
7月11日
- 题目描述
长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,删除线性表中所有值为x的数据元素。- 输入
输入包含一个整数n代表顺序表L长度,一个x代表要删除的元素。
接下来包含n个整数,代表顺序表L中的元素。- 输出
输出删除元素x后的顺序表。- 样例输入
5 2
1 3 2 5 2- 样例输出
1 3 5
思考:只需定义一个变量k统计不等于x的个数,并把这个不等于x的数放在第k个的位置。
#include
using namespace std;
typedef struct SqList{
int *data;
int length;
}SqList;
int main(){
SqList s;
int d;
scanf("%d",&s.length);
scanf("%d",&d);
s.data = (int *) malloc(sizeof(int) * s.length);
for (int i = 0; i < s.length; ++i){
scanf("%d",&s.data[i]);
}
//用k记录线性表L中 不等于 x的个数,边扫描,便统计k,不等于 x的元素移动到第k个位置上
int k = 0;
for (int i = 0; i < s.length; ++i){
if (s.data[i] != d){
s.data[k++] = s.data[i];
}
}
s.length = k;
for (int i = 0; i < s.length; ++i){
printf("%d ",s.data[i]);
}
printf("\n");
free(s.data);
return 0;
}
- 题目描述
假设一个算术表达式中包含圆括号,方括号,花括号3种类型的括号,编写算法来判别表达式中括号是否配对。- 输入
输入包含多组测试用例。
对于每组测试样例,包括一个仅由 ‘(’,’)’,’[’,’]’,’{’,’}'组成的字符串s。- 输出
若s是合法的括号串,输出"yes",否则,输出"no"。- 样例输入
{()}(]- 样例输出
yes
no
#include
using namespace std;
//定义一个顺序栈
#define MAXSIZE 100100
typedef struct Stack{
int data[MAXSIZE];
int top;
}Stack;
int main(){
Stack s;
s.top = -1;
char str[MAXSIZE];
while(scanf("%s",&str)!=EOF){
int len = strlen(str);
for (int i = 0; i < len; ++i){
//左括号入栈,右括号出栈
if (str[i] == '(' || str[i] == '[' || str[i] == '{'){
s.data[++s.top] = str[i];
} else {
char pop = s.data[s.top--];
if (pop == '(' && str[i] == ')'){
continue;
} else if (pop == '[' && str[i] == ']'){
continue;
} else if (pop == '{' && str[i] == '}'){
continue;
} else{
printf("no\n");
s.top = -3;
break;
}
}
}
if (s.top == -1){
printf("yes\n");
} else {
if (s.top !=-3){
printf("no\n");
}
s.top = -1;
}
}
return 0;
}
7月12日
- 题目描述
PIPI现在有一段由小写字母组成的文本s,他每天的工作就是找到文本中两个相邻并且相同的字母,然后删除它们。注意这个过程是递归的,比如:
“abbac”->“aac”->“c”。
返回PIPI删除的文本。- 输入
输入一行,代表文本s。(1<=|s|<=1e5).- 输出
输出一行,代表PIPI经过上述操作之后得到的文本。- 样例输入
abbbac- 样例输出
abac
#include
using namespace std;
#define MaxSize 100000
int main(){
char s[MaxSize];
scanf("%s",&s);
int len = strlen(s);
int sum = 0;//记录相邻位置不相等的个数
int sum2 = 0; // 上一次相邻位置不相等的个数
while (true){
int i = 1;
for (i = 1; i < len; ++i){
if(s[i-1] != s[i]){
s[sum++] = s[i-1];
} else {
i++;
}
}
if (i == len){
s[sum++] = s[i-1];
}
if (sum==len ||sum == sum2 || sum == 1){
break;
} else {
sum2 = sum;
len = sum;
sum = 0;
}
}
len = sum;
for (int i = 0; i < len; ++i){
printf("%c",s[i]);
}
printf("\n");
return 0;
}
7月13日
- 题目描述
给定一个长度为n的单链表,删除倒数第K的节点,然后从头到尾输出每个节点的值。- 输入
第一行包含两个整数N,k,k<=N.
第二行包含N个整数,代表从表头到表尾每个节点的值。
你需要建立单链表把这N个数串起来~- 输出
按顺序输出删除了倒数第K个节点后每个节点的值。- 样例输入
5 2
1 2 3 4 5- 样例输出
1 2 3 5
#include
using namespace std;
//单链表
typedef struct ListNode{
int data;
struct ListNode *next;
}ListNode, *LinkedList;
int main(){
//尾插法构造单链表
LinkedList list;
list = (ListNode *) malloc(sizeof(ListNode));
list->next = NULL;
ListNode *r = list;
int n;
int k;
scanf("%d",&n);
scanf("%d",&k);
ListNode *p;//要插入的结点
list->next = p;
for (int i = 0; i < n; ++i){
p = (ListNode *) malloc(sizeof(ListNode));
scanf("%d",&p->data);
r->next = p;
r = p;
}
//最后一个结点指向NULL
r->next = NULL;
//删除
//找到第n-k个
ListNode *q = list;
for (int i = 0; i < n-k; ++i){
q = q->next;
}
//删除第n-k+1个
ListNode *m = q->next;
q->next= q->next->next;
free(m);
n--;
q = list;
for (int i = 0; i < n; ++i){
q = q->next;
printf("%d ",q->data);
}
printf("\n");
return 0;
}
7月14日
- 题目描述
反转长度为N的单链表从位置 L 到 R 的子段。请在常数空间复杂度下使用一趟扫描完成反转。- 输入
第一行三个整数N,L,R,1<=L<=R<=N
接下来N个数表示N个节点的值- 输出
输出反转后的单链表节点值- 样例输入
5 2 4
1 2 3 4 5- 样例输出
1 4 3 2 5
这题有代码有15%的错误,找了半天没找到,先保存一下代码,有时间再修改:
#include
using namespace std;
//单链表
typedef struct ListNode{
int data;
struct ListNode *next;
}ListNode,*LinkedList;
int main(){
int n,l,r;
scanf("%d",&n);
scanf("%d",&l);
scanf("%d",&r);
LinkedList list = (ListNode *) malloc(sizeof(ListNode));
ListNode *t = list; //t指向尾结点,尾插法
ListNode *s;
for (int i = 0; i < n; ++i){
s = (ListNode *) malloc(sizeof(ListNode));
scanf("%d",&s->data);
t->next = s;
t = s;
}
t->next = NULL;
//逆置链表
//找到第l-1个结点
ListNode *a = list;
ListNode *p;
for (int i = 0; i < l-1; ++i){
a = a->next;
}
//第l个结点
p = a->next;
//保留第l个结点
ListNode *b = p;
ListNode *q = p->next,*m;
for (int i = l; i < r; ++i){
m = q->next;
q->next = p;
p = q;
q = m;
}
b->next = m;
a->next = p;
ListNode *w= list->next;
while (w != NULL){
printf("%d ",w->data);
w = w->next;
}
printf("\n");
return 0;
}
7月15日
- 题目描述
给定带头结点的单链表L,假设L存储了n个元素(n为奇数,是未知的)。设计算法返回该链表中间的那个元素。要求仅对链表进行一次遍历。- 输入
输入N个数字,不用关心N是多少,使用while循环读入链表中元素,直至EOF。(0- 输出
输出链表最中间的元素。- 样例输入
1 2 3 4 5- 样例输出
3
#include
using namespace std;
//单链表
typedef struct ListNode{
int data;
struct ListNode *next;
}ListNode,*LinkedList;
int main(){
LinkedList list = (ListNode *) malloc(sizeof(ListNode));
int n;
ListNode *r = list;
ListNode *s;
while (scanf("%d",&n)!=EOF){
s = (ListNode *) malloc(sizeof(ListNode));
s->data = n;
r->next = s;
r = s;
}
r->next = NULL;
ListNode *p = list;
ListNode *q = list;
while (q && q->next){
p = p->next;
q = q->next->next;
}
printf("%d\n",p->data);
return 0;
}
7月20日
- 题目描述
给定一个二叉树,找出其最大深度。
最大深度是从根节点到最远叶子节点的最长路径上的节点数量。- 输入
输入一行,按照先序输入一棵二叉树,其中空节点用 -1 表示。- 输出
输出一行代表二叉树的最大深度。- 样例输入
1 2 -1 -1 3 4 -1 -1 -1- 样例输出
3
#include
using namespace std;
typedef struct BiNode{
int data;
struct BiNode *lchild;
struct BiNode *rchild;
}*BiTree;
void CreateTree(BiTree &T){
//按照先序序列创建一棵二叉树
int data;
scanf("%d",&data);
if(cin.get()!='\n'){
if(data==-1){
T=NULL;
}else{
T=(BiTree)malloc(sizeof(BiNode));
T->data=data;
CreateTree(T->lchild);
CreateTree(T->rchild);
}
}
}
// 通过后序递归遍历二叉树T求二叉树高度:LRN
int HeithByPostOrder(BiTree T){
if(T==NULL) return 0; // 空树
int lh=HeithByPostOrder(T->lchild); // 递归访问左子树
int rh=HeithByPostOrder(T->rchild); // 递归访问右子树
return (lh>rh?lh:rh) + 1; // 自己的高度等于子树中最大高度加1
}
int main(){
BiTree T;
CreateTree(T);
printf("%d",HeithByPostOrder(T));
return 0;
}
7月21日
- 题目描述
已知线性表中的元素以递增序列排列,并以单链表作存储结构。设计算法删除表中所有值相同的多余元素(使得操作后的线性表中所有的值均不相同),同时释放被删结点空间,并分析算法的时间复杂度。- 输入
第一行输入一个正整数n,表示元素个数,n<=100。
第二行输入n个正整数元素,保证元素以递增排列,元素的值<=100。- 输出
输出删除相同元素后的链表。- 样例输入
5
1 1 3 4 4- 样例输出
1 3 4
#include
using namespace std;
//单链表
typedef struct ListNode{
int data;
struct ListNode *next;
}ListNode,*LinkedList;
int main(){
LinkedList L = (ListNode *) malloc(sizeof(ListNode));
int n;
cin>>n;
//尾插法构造单链表
ListNode *r = L;
//要插入的结点
ListNode *s;
for (int i = 0; i < n; ++i){
s = (ListNode *) malloc(sizeof(ListNode));
cin>>s->data;
r->next = s;
r = s;
}
r->next = NULL;
//第一个结点
ListNode *p = L->next;
//要删除的结点
ListNode *m;
while (p->next){
if (p->data == p->next->data){
//删除结点 p->next
m = p->next;
p->next = m->next;
free(m);
} else {
p = p->next;
}
}
ListNode *q = L->next;
while (q){
cout<<q->data<<" ";
q = q->next;
}
cout<<endl;
return 0;
}