前两天在阿里面试,面试官问我看过什么书?是否看过《编程之美》、《编程珠玑》?去年的这个时候接触过两本书,之所以说是接触过而不是看过,是因为当时看的是英文版,看了几页就没再坚持看下去,现在借了本中文版的《编程珠玑》,希望能利用找工作的这段时间好好看一看。
看了前两章,感觉这上面的算法不是很深奥,而是设的很巧妙。作者对于同一个问题,能从不同的角度、不同的深度去挖掘,比如这个问题:将一个n元数组向左移动i个位置。作者给出了五种解法,我用C++实现了其中的四种算法,四种算法的实现如下:
/* 方法一:将数组的前num项复制到一个临时数组b中,再将a中剩余元素左移num位,最后将b复制到a的后num位中 */
#include <iostream>
using namespace std;
int main()
{
int a[10]={0,1,2,3,4,5,6,7,8,9};
int num=3;
int b[num];
for(int i=0;i<num;i++)
b[i]=a[i];
for(int i=num;i<10;i++)
a[i-num]=a[i];
for(int i=0;i<num;i++)
a[10-num+i]=b[i];
for(int i=0;i<10;i++)
cout<<a[i]<<" ";
return 0;
}
/* 方法二:实现将数组元素左移一位,然后循环num次即可 */
#include <iostream>
using namespace std;
int main()
{
int a[10]={0,1,2,3,4,5,6,7,8,9};
int num=3;
int count=num;
while(count--)
{ //实现数组元素左移一位
int t=a[0];
for(int i=1;i<10;i++)
a[i-1]=a[i];
a[10-1]=t;
}
for(int i=0;i<10;i++)
cout<<a[i]<<" ";
return 0;
}
/* 方法三:将0,num,2*num,……作为一组,执行左移一位,对1,2,……,num-1组的元素做同样的处理 */
#include <iostream>
using namespace std;
int main()
{
int a[10]={0,1,2,3,4,5,6,7,8,9};
int num=3;
for(int i=0;i<num;i++)
{
int t=a[i];
int j;
for(j=i+num;j<10;j+=num)
a[j-num]=a[j];
a[j-num]=t;
}
for(int i=0;i<10;i++)
cout<<a[i]<<" ";
return 0;
}
/* 方法四:我们将问题看做是把数组ab转换成ba,通过数学中的求逆运算,我们可以通过对ab几次求逆最终得到ba,求逆过程为:ab->a'b->a'b'->(a'b')'=ba */
#include <iostream>
using namespace std;
int main()
{//将数组a中第i项到j项进行倒置(求逆),即第i项与第j项互换,第i+1项与第j-1项互换,……
int a[10]={0,1,2,3,4,5,6,7,8,9};
int num=3;
void reverse(int *a,int i,int j);
reverse(a,0,num-1);
reverse(a,num,10-1);
reverse(a,0,10-1);
for(int i=0;i<10;i++)
cout<<a[i]<<" ";
return 0;
}
void reverse(int *a,int i,int j)
{
int t;
while(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
i++;
j--;
}
}
越好的算法,不是越高深的,而是使问题看起来更简单的!