1. 给定一个如下格式的字符串(1,(2,3),(4,(5,6),7))括号内的元素可以是数字,也可以是另一个括号,请实现一个算法消除嵌套的括号,比如把上面的表达式变成:(1,2,3,4,5,6,7),如果表达式有误请报错。
解:
<span style="font-size:18px;"><span style="font-size:18px;"><pre name="code" class="cpp">void checkWipe(char *s)
{
static<char> s1; //正序存放字符串
static<char> s2; //存放(
static<char> s3; //倒序存放字符串
if(s==NULL)
return;
while(*s!='\0')
{
if(*s=='(')
s2.push();
else if(*s==')')
{
char temp=s2.pop();
if(temp!='(')
{
printf("错误");
return;
}
}else{
s1.push();
}
s++;
}
while(!s1.isEmpty())
{
s2.push(s1.pop());
}
cout<<"(";
while(!s2.isEmpty())
{
cout<<s2.pop();
}
cout<<")";
}</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#define M 8
#define N 5
int cmp(const void *a, const void *b)
{
int *x = (int *)a;
int *y = (int *)b;
return (*x) - (*y);
}
int main(void)
{
int A[] = {-1, 2 ,39 ,10, 6, 11, 188, 10};
int B[] = {39 ,8 , 10, 6, -1};
//对数组A和数组B进行快排
qsort(A, M, sizeof(int), cmp);
qsort(B, N, sizeof(int), cmp);
//FindIntersection(A, B);
int i = 0, j = 0;
int cnt = 0;
int result[M > N ? M : N];//保存集合的结果
//设置i、j索引,分别指向数组A和B,相等则同时移动,不相等则移动较小值的索引
while(i < M && j < N)
{
if(A[i] == B[j])
{
result[cnt] = A[i];
i++;
j++;
cnt++;
}
else if(A[i] < B[j])
{
i++;
}
else
{
j++;
}
}
for(i = 0; i < cnt; i++)
{
printf("%4d", result[i]);
}
return 0;
} </span></span>
3.请设计一个排队系统,能够让每个进入队伍的用户都能看到自己在队中所处的位置和变化。队伍可能随时有人加入和退出,当有人退出影响到用户的位置排名时需要即时反馈到用户。
需要用到设计模式的东西,暂时还未解答!
4.数轴上从左到右有n个点、a[0] a[1]……、给定一根长度为L的绳子、求绳子最多覆盖其中几个点?
解:
<span style="font-size:18px;"><span style="font-size:18px;">int getMax(int a[],int n,int L)
{
int temp,max=1;
int begin=0,end=1;
while(end<n)
{
if(a[end]-a[begin]>L)
{
temp=end-begin;
if(temp>max)
max=temp;
begin++;
}else
end++;
}
return max;
}</span></span>
5.合并两个排序链表。
<span style="font-size:18px;"><span style="font-size:18px;">List *merge(List *head1,List *head2)
{
if(head1==NULL)
return head2;
if(head2==NULL)
return head1;
List *p1=head1,*p2=head2,*p,*head;
if(p1->data<p2->data)
{
head=p1;
p1=p1->next;
}else{
head=p2;
p2=p2->next;
}
p=head;
while(p1&&p2)
{
if(p1->data<p2->data)
{
p->next=p1;
p1=p1->next;
}else{
p->next=p2;
p2=p2->next;
}
p=p->next;
}
if(p1==NULL)
p->next=p2;
if(p2==NULL)
p->next=p1;
return head;
} </span></span>
6. 一个大文件有100亿个数,乱序排列,求其中位数,内存限制为512M。
解:采用分而治之的策略。
顺序遍历这100亿个数,采用hash(key)%100的策略,将这些数平均的分配到这100个小文件中,然后对每个小文件中的数进行排序,使之有序,然后再对着100个小文件使用归并排序,最后求有序序列的中位数。即序列个数为2n,中位数为第n,n+1;为2n+1,中位数为第n+1个;
7.最长回文子串。
<span style="font-size:18px;"><span style="font-size:18px;">void LongestPalindrome(char *s, int n)
{
int i, j, max,middle=0,begin;
char *sb;
if (s == 0 || n < 1) return 0;
max = 0;
for (i = 0; i < n; ++i) { // i is the middle point of the palindrome
for (j = 0; (i-j >= 0) && (i+j < n); ++j) // if the lengthof the palindrome is odd
if (s[i-j] != s[i+j]) break;
if (j*2+1 > max)
{
middle=i;
max = j * 2 + 1;
}
for (j = 0; (i-j >= 0) && (i+j+1 < n); ++j) // for theeven case
if (s[i-j] != s[i+j+1]) break;
if (j*2+2 > max)
{
max = j * 2 + 2;
middle =i;
}
}
if(max%2==0)
j=(max-2)/2;
else
j=(max-1)/2;
begin=middle-j;
int k=0;
while(k<max)
{
cout<<s[begin++];
k++;
}
}
</span></span>
8.判断字符串s2是否是s1的子串。
<span style="font-size:18px;"><span style="font-size:18px;">bool isSubString(char *s1,char *s2)
{
if(s1==NULL || s2==NULL)
return true;
int i=0,j=0;
int n1=strlen(s1);
int n2=strlen(s2);
while(s1[i]!='\0')
{
if(s2[0]==s1[i])
{
j=0;
int k=i;
while(k<n1&&j<n2)
{
if(s1[k]!=s2[j])
break;
k++;
j++;
}
if(j==n2)
return true;
}
i++;
}
return false;
}</span></span>
9.最长公共子串问题
<span style="font-size:18px;"><span style="font-size:18px;">int LCS(const char *str1 , int len1 , const char *str2 , int len2 , char *&lcs)
{
if(NULL == str1 || NULL == str2)
{
return -1; //空参数
}
// 压缩后的最长子串记录向量
int *c = new int[len2+1];
for(int i = 0 ; i < len2 ; ++i)
{
c[i] = 0;
}
int max_len = 0; //匹配的长度
int pos = 0; //在str2上的匹配最末位置
for(int i = 0 ; i < len1 ; ++i)
{
for(int j = len2 ; j > 0 ; --j) //更新时从后往前遍历
{
if(str1[i] == str2[j-1])
{
c[j] = c[j-1] + 1;
if(c[j] > max_len)
{
max_len = c[j];
pos = j-1;
}
}
else
{
c[j] = 0;
}
}
}
if(0 == max_len)
{
return 0;
}
// 得到公共子串
lcs = new char[max_len];
for(int i = 0 ; i < max_len ; ++i)
{
lcs[i] = str2[pos-max_len+1+i];
}
cout<<"pos = "<<pos<<endl;
delete [] c;
return max_len;
} </span></span>
10.最长公共子序列
<span style="font-size:18px;">/**
找出两个字符串的最长公共子序列的长度
** author :liuzhiwei
** data :2011-08-15
**/
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int LCSLength(char* str1, char* str2, int **b)
{
int i,j,length1,length2,len;
length1 = strlen(str1);
length2 = strlen(str2);
//双指针的方法申请动态二维数组
int **c = new int*[length1+1]; //共有length1+1行
for(i = 0; i < length1+1; i++)
c[i] = new int[length2+1]; //共有length2+1列
for(i = 0; i < length1+1; i++)
c[i][0]=0; //第0列都初始化为0
for(j = 0; j < length2+1; j++)
c[0][j]=0; //第0行都初始化为0
for(i = 1; i < length1+1; i++)
{
for(j = 1; j < length2+1; j++)
{
if(str1[i-1]==str2[j-1]) //由于c[][]的0行0列没有使用,c[][]的第i行元素对应str1的第i-1个元素
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=0; //输出公共子串时的搜索方向
}
else if(c[i-1][j]>c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=1;
}
else
{
c[i][j]=c[i][j-1];
b[i][j]=-1;
}
}
}
/*
for(i= 0; i < length1+1; i++)
{
for(j = 0; j < length2+1; j++)
printf("%d ",c[i][j]);
printf("\n");
}
*/
len=c[length1][length2];
for(i = 0; i < length1+1; i++) //释放动态申请的二维数组
delete[] c[i];
delete[] c;
return len;
}
void PrintLCS(int **b, char *str1, int i, int j)
{
if(i==0 || j==0)
return ;
if(b[i][j]==0)
{
PrintLCS(b, str1, i-1, j-1); //从后面开始递归,所以要先递归到子串的前面,然后从前往后开始输出子串
printf("%c",str1[i-1]); //c[][]的第i行元素对应str1的第i-1个元素
}
else if(b[i][j]==1)
PrintLCS(b, str1, i-1, j);
else
PrintLCS(b, str1, i, j-1);
}
int main(void)
{
char str1[100],str2[100];
int i,length1,length2,len;
printf("请输入第一个字符串:");
gets(str1);
printf("请输入第二个字符串:");
gets(str2);
length1 = strlen(str1);
length2 = strlen(str2);
//双指针的方法申请动态二维数组
int **b = new int*[length1+1];
for(i= 0; i < length1+1; i++)
b[i] = new int[length2+1];
len=LCSLength(str1,str2,b);
printf("最长公共子序列的长度为:%d\n",len);
printf("最长公共子序列为:");
PrintLCS(b,str1,length1,length2);
printf("\n");
for(i = 0; i < length1+1; i++) //释放动态申请的二维数组
delete[] b[i];
delete[] b;
system("pause");
return 0;
} </span>
11.
.
<span style="font-size:18px;"><span style="font-size:18px;">bool isRuledTree(Node *root)
{
if(root==NULL)
return true;
Node *Queue[100],*p;
int front=0,rear=0;
int max=1,min=-1;//用来记录叶子节点的最大深度和最小深度。
Queue[++rear]=root;
int level=rear,depth=0;
while(front<rear)
{
p=Queue[++front];
if(p->lchild!=NULL)
Queue[++rear]=p->lchild;
if(p->rchild!=NULL)
Queue[++rear]=p->rchild;
if(level==front)
{
depth++;
level=rear;
}
if(p->lchild==NULL&&p->rchild==NULL)
{
if(min==-1)
min=depth;
else
min=min>depth?depth:min;
max=max>depth?max:depth;
}
}
if(max-min<=1)
return true;
else
return false;
}
</span></span>
12.字符串的排列与组合
字符串的组合:
//函数功能 : 从一个字符串中选m个元素
2 //函数参数 : pStr为字符串, m为选的元素个数, result为选中的
3 //返回值 : 无
4 void Combination_m(char *pStr, int m, vector<char> &result)
5 {
6 if(pStr == NULL || (*pStr == '\0'&& m != 0))
7 return;
8 if(m == 0) //递归终止条件
9 {
10 for(unsigned i = 0; i < result.size(); i++)
11 cout<<result[i];
12 cout<<endl;
13 return;
14 }
15 //选择这个元素
16 result.push_back(*pStr);
17 Combination_m(pStr + 1, m - 1, result);
18 result.pop_back();
19 //不选择这个元素
20 Combination_m(pStr + 1, m, result);
21 }
22 //函数功能 : 求一个字符串的组合
23 //函数参数 : pStr为字符串
24 //返回值 : 无
25 void Combination(char *pStr)
26 {
27 if(pStr == NULL || *pStr == '\0')
28 return;
29 int number = strlen(pStr);
30 for(int i = 1; i <= number; i++)
31 {
32 vector<char> result;
33 Combination_m(pStr, i, result);
34 }
35 }
字符串的排列:
- void Permutation(char* pStr, char* pBegin)
- {
- assert(pStr && pBegin);
- if(*pBegin == '\0')
- printf("%s\n",pStr);
- else
- {
- for(char* pCh = pBegin; *pCh != '\0'; pCh++)
- {
- swap(*pBegin,*pCh);
- Permutation(pStr, pBegin+1);
- swap(*pBegin,*pCh);
- }
- }
- }
13.有这样一个数组A,大小为n,相邻元素差的绝对值都是1,如A={4,5,6,5,6,7,8,9,10,9},现在给定数组A和目标整数t,请找到t在A中的位置
<span style="font-size:18px;"><span style="font-size:18px;">int find(int A[],int n,int key)
{
if(A==NULL || n<1)
return -1;
int j=0; //下标
int m; //偏移量
while(1)
{
if(A[j]==key) //找到,返回下标
return j;
m=A[j]-key;
m= m<0?-m:m;
j=j+m;
if (j+m>n-1) //没有找到,返回-1;
{
return -1;
}
}
}</span></span>
14.判断一棵树是否是二分查找树
思路:二分查找树的中序遍历是有序的,所以可以利用中序遍历来判定树是否是二分查找树
<span style="font-size:18px;">bool check(BTNode *T,int preValue)
{
if(T==NULL)
return true;
if(check(T->lchild,preValue)) //检查左子树是否是二分查找树
{
if(T->data>preValue)
{
preValue=T->data;
return check(T->rchild,preValue); //检查右子树是否是二分查找树
}
else
return false;
} else
return false;
}</span>
其中,preValue的初始值为整数的最小值。
详解:http://blog.csdn.net/sgbfblog/article/details/7771096
15.连续子数组的最大和。
<span style="font-size:18px;"> int getSubMax(int data[],int n)
{
if(data==NULL || n<1)
{
cout<<"参数有误";
return 0;
}
int currentSum=0,maxSum=0;
for(int i=0;i<n;i++)
{
currentSum+=data[i];
if(currentSum<0)
{
currentSum=0;
}else
{
if(maxSum<currentSum)
maxSum=currentSum;
}
}
return maxSum;
}</span>
16.磁盘里有100T的数据,每一个数据项有一个Key,数据项按key的升序排列,但是key不连续。每个数据项的大小不一样,但是都不超过1M,每一个数据项以特定的标识符结束。现在内存大小为256M,如何找到指定Key的数据项。
思路:采用层次遍历的思想。
Node *Connect(Node *root)
{
if(root==NULL)
return root;
Node *Queue[100],*p=root,*prev=NULL;
int front=0,rear=0;
Queue[++rear]=root;
int level=rear; //标记每一层的最后一个节点。
while(front<rear)
{
p=Queue[++front];
if(prev==NULL)
{
prev=p;
}else
{
prev->slib=p;
prev=p;
}
if(p->lchild!=NULL)
Queue[++rear]=p->lchild;
if(p->rchild!=NULL)
Queue[++rear]=p->rchild;
if(level==front)
{
p->slib=NULL;
prev=NULL;
level=rear;
}
}
}