1、两个已排序数组合并以后的中位数
int getMedin(int A[],int m,int B[],int n)
{
int p1=0;
int p2=0;
int mid=p1;
int flag=0;
for(int i=0;i<(m+n)/2;)
{
while(p1<m&&p2<n&&i<(m+n)/2&&!flag)
{
if(B[p2]<A[mid])
{
++p2;++i;
}
else
{
mid=p2;
flag=1;
++p1;
++i;
}
}
while(p1<m&&p2<n&&i<(m+n)/2&&flag)
{
if(A[p1]<B[mid])
{
++p1;++i;
}
else
{
mid=p1;
flag=0;
++p2;
++i;
}
}
while((p1==m||p2==n)&&i<(m+n)/2)
{
++mid;
++i;
}
}
if(flag)
return B[mid];
return A[mid];
}
2、已知两个链表各自有序,写一个程序使他们合并起来依然有序
struct node
{
int _data;
node* _next;
};
void merge(node *head1,node *head2,node *head3)
{
node *pl1=head1->_next;
node *pl2=head2->_next;
node *pl3;
head3=head1;
head3->_next=NULL;
free(head2);
pl3=head3;
while(pl1!=NULL&&pl2!=NULL)
{
if(pl1->_data<=pl2->_data)
{
pl3->_next=pl1;
pl1=pl1->_next;
pl3=pl3->_next;
}
else
{
pl3->_next=pl2;
pl2=pl2->_next;
pl3=pl3->_next;
}
}
pl3->_next=NULL;
if(pl1!=NULL)
pl3->_next=pl1;
if(pl2!=NULL)
pl3->_next=pl2;
}
如果想得到相反的序列就用头插法
3、字符串匹配查找
#include<iostream>
using namespace std;
//str1指向带查找字符串,str2指向待匹配字符串
char *strfind(const char *str1,const char *str2)
{
const char *ptr1=str1;
const char *ptr2=str2;
const char *result=(char *)0;
while(*ptr1!='\0') //查找字符串没有结束
{
if(*ptr1==*ptr2)
{
result=ptr1;
while(*ptr2!='\0')
{
if((*ptr1!='\0')&&(*ptr1==*ptr2))
{
ptr1++;
ptr2++;
}
else
break;
}
if(*ptr2=='\0')
return (char *)result;
else if(*ptr1!='\0')
{
ptr2=str2;
ptr1=result+1;
result=(char *)0;
}
else
{
break;
}
}
ptr1++;
}
return (char*)0;
}
int main()
{
char s1[]="abcdefghijk";
char s2[]="def";
char *ptr=strfind(s1,s2);
cout<<*ptr<<endl;
return 0;
}
这是一道风行的笔试题,其实代码比较简单,就是里面的逻辑关系要考虑清楚,不能漏掉任何一种情况
4、反转字符串,保持子串相对位置不变
思路:先将字符串里面的子串反转,然后再将整个字符串反转
void reverse(char *str,int m,int n)
{
if(!str) //字符串为空直接退出
exit(0);
if(m==n)//子串只有一个元素不用交换
return;
for(int i=m,j=n;i<j;i++,j--) //交换元素
{
char temp=str[i];
str[i]=str[j];
str[j]=temp;
}
}
int main()
{
char str[]="a bc def gh ijk";
int len=strlen(str);
int m=0,n=0;
for(int i=0;i<len;i++)
{
if(str[i]==' ')
{
n=i-1;
reverse(str,m,n); //交换子串
m=i+1;
n=i+1;
}
}
reverse(str,0,len-1);//交换整个数组
for(int i=0;i!=len;i++)
cout<<str[i]<<" ";
cout<<endl;
return 0;
}
5、给定一数组a[N],我们希望构造数组b [N],其中b[j]=a[0]*a[1]…a[N-1] / a[j],在构造过程中,不允许使用除法
#include<iostream>
using namespace std;
void printfn(int a[],int n)
{
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
int main()
{
const int MAX=5;
int a[MAX]={1,2,3,4,5};
int b[MAX];
b[0]=1;
for(int i=1;i<MAX;i++)
{
b[i]=b[i-1]*a[i-1];
}
/*
b[0]=1;
b[1]=a[0];
b[2]=a[0]*a[1];
b[3]=a[0]*a[1]*a[2];
b[4]=a[0]*a[1]*a[2]*a[3];
*/
for(int i=MAX-1;i>0;i--)
{
b[i]*=b[0];
b[0]*=a[i];
}
/*
b[4]=b[4]=a[0]*a[1]*a[2]*a[3]; b[0]=a[4];
b[3]=b[3]*a[4]=a[0]*a[1]*a[2]*a[4]; b[0]=a[4]*a[3];
b[2]=b[2]*a[2]=a[0]*a[1]*a[3]*a[4]; b[0]=a[4]*a[3]*a[2];
b[1]=b[1]*b[4]=a[0]*a[2]*a[3]*a[4]; b[0]=a[4]*a[3]*a[2]*a[1];
*/
printfn(a,5);
printfn(b,5);
return 0;
}
6、如下为类型MyString的声明,请为该类型添加赋值运算符函数
class CMyString
{
public:
CMyString(char* pdata=NULL);
CMyString(const CMyString& str);
CMyString& operator=(const CMyString& str);
~CMyString(void);
private:
char* m_data;
};
写出的代码要关注以下几点
1、是否把返回值声明为该类型的引用,只有返回一个引用才允许连续赋值。
2、是否传入的参数是常量引用
3、是否释放实例本身已有的内存
4、是否判断传入的参数和当前的实例是不是同一个实例
综合一下可以写出
CMyString& CMyString::operator=(const CMyString &str)
{
if(this==&str)
return *this ;
delete []m_data;
m_data=NULL;
m_data=new char[strlen(str.m_data)+1];
strcpy(m_data,str.m_data);
return *this;
}
但是这并不是很完善的代码
参照effective C++中的条款11
如果new char导致异常,CMyString最终会持有一个指针指向一块被删除的char[],这样的指针有害,你无法安全的删除它们,甚至无法安全的读取它们,唯一能对它们做的安全事情是付出许多调试找出错误的根源。
为了避免异常,对代码做出以下的修改
CMyString& CMyString::operator=(const CMyString &str)
{
if(this!=&str)
{
CMyString strTemp(str);
char *ptemp=strTemp.m_data;
strTemp.m_data=m_data;
m_data=ptemp;
}
return *this;
}
先创建一个临时实例strTemp,接着把strTemp.m_data和自身实例的m_data作交换。由于strTemp是一个局部变量,当程序运行到if外面时就会自动调用析构函数,相当于用析构函数释放之前实例的内存。