闲来无事总结3个我认为比较好的算法,很简单,但有趣。我们应该学会欣赏简单的东西,拒绝钻进复杂的东西里面,比如股市...
这三个算法分别为大数乘法,求交集算法,将一个数拆成连续整数和算法以及8位倒置算法。这些算法都非出自本人,但是本人实现了一个。
1.大数乘法:这个算法很著名,它可以突破计算机的限制从而计算一些很大的数,它的效率是重要的,但本文仅仅从逻辑角度来分析,先不分析时间空间复杂性。
我们人在计算乘法的时候用的是竖式,然后把每一行的结果加起来(位相错),最后得到答案,但是在计算机中,我见过很多算法是保留一个变量作为进位,最后一古脑把进位直接加到和里面,看惯了那种方法,看看下面方法如何,它可是完全和我们人的方法是一致的 :(作者源代码是错误,以下是我改正后的)
void main()
{
string num1,num2;//被乘数和乘数,考虑到大整数,用string装入
cout
cin>>num1>>num2;
const char *p1=num1.c_str(); //转为char *
const char *p2=num2.c_str();
int length=strlen(p1)+strlen(p2);
char *p=new char [length]; //结果放在字符数组中
int i,j;
for(i=0;i<length><p> {</p> <p> p[i]='0'; //初始化结果数组,开始全为'0',对应数字0</p> <p> }</p> <p> p[i]='/0';</p> <p> int carry=0; //进位初时设为0</p> <p> for(i=strlen(p1)-1;i>=0;--i)</p> <p> {</p> <p> carry=0;//每一行都将进位清0,绝对不影响下一循环</p> <p> for(j=strlen(p2)-1;j>=0;--j)</p> <p> {</p> <p> carry+=(p1[i]-'0')*(p2[j]-'0')+(p[i+j+1]-'0');</p> <p> p[i+j+1]=carry%10+'0';</p> <p> carry/=10;</p> <p> }</p> <p> p[i+j+1]=carry%10+'0';</p> <p> }</p> <p> int b =0;</p> <p> for(i=0;i<strlen><p> {</p> <p> if(p[i]=='0'&&b == 0)</p> <p> {</p> <p> continue;</p> <p> }</p> <p> b = 1;</p> <p> cout </p> <p> }</p> <p> cout </p> <p> delete [] p;</p> <p>} </p> <p>2.求交集算法: <br>这个算法太老了,我发现很多时候都是用直接一个一个比较的办法求解,当然可以用哈希表,不过有点高射炮打蚊子的味道,于是我建议了一种算法(原创),实质上也是一个一个比较,但简捷了很多:</p> <p>int main()</p> <p>{</p> <p> int a[]={4,6,7,8,9,10,11,15};</p> <p> int b[]={2,3,4,6,7,9,10,11,15,20};</p> <p> int p1[16]={0};//把p1分配足够大即可,p1的长度是两个数组中最大的数加1,小小损失空间效率,如果有很大数的话</p> <p> int i = 0;</p> <p> for(i=0;i </p> <p> {</p> <p> p1[a[i]] = 1;</p> <p> }</p> <p> for(i=0;i </p> <p> {</p> <p> if(p1[b[i]]!=0)</p> <p> printf("%d ",b[i]);//此处输出的就是结果!</p> <p> }</p> <p>}</p> <p>说明一点:数组可以不排序,乱续即可 <br>3.将一个数拆成连续整数和算法 <br>这个也很经典了,我的实现如下:</p> <p>int main()</p> <p>{</p> <p> int n = 123456;</p> <p> int i = 1;</p> <p> for( i = 1;i </p> <p> {</p> <p> int j = 0;</p> <p> for( j = 0; j </p> <p> {</p> <p> if( 2*n == 2*i*j + i*i -i )//用等差数列推导</p> <p> {</p> <p> int q = j;</p> <p> int t = 0;</p> <p> for( t = 1; t </p> <p> t==i:printf( "%d ", q-- )?printf( "%d +", q-- );</p> <p> printf( "= %d/n", n );</p> <p> }</p> <p> }</p> <p> }</p> <p>}</p> <p>我的实现用的是等差数列:如果i是首数,那么i+i+1+i+1+1...这可以用等差数列表示。还有一种很好的办法(比我的好):</p> <p>public class Test {</p> <p> public static void main(String[] args) {</p> <p> int left, right;</p> <p> int sum;</p> <p> //int given = Integer.parseInt(args[0]);</p> <p> int given = 27;//指定的数</p> <p> int count = 0;</p> <p> for (sum = 0 ,right=1; sum </p> <p> }</p> <p> for(left = 1,right--;left </p> <p> if(sum>given)</p> <p> sum-=(left++);</p> <p> else{</p> <p> if(sum==given){</p> <p> System.out.println(given+"= sum from "+left+"to"+ right);</p> <p> count++;</p> <p> }</p> <p> sum+=(++right);</p> <p> }</p> <p> }</p> <p> if(count>0){</p> <p> System.out.println("一共有"+count+"解");</p> <p> }</p> <p> else{</p> <p> System.out.println("无解");</p> <p> }</p> <p> }</p> <p>}</p> <p>这 个算法实现了一种微调的思想,就是加加减减,细细品味吧。先将微调尺调到给定数据的大致位置,然后开始微调,也就是前面的继续加,加过了就从后面减,本身就有连续的思想在里面,就好像买瓜子,老大爷先大致给你个差不离,然后放到秤上,多了就减一点,少了就再加点,仔细想想,不是吗? <br>4.8位倒置: <br>这个算法在底层用的比较多,涉及到移位啊,等等的方法也不少,但是有一种二分法,其想法非常好,有点递归的意思,不信,看看:</p> <p>x = (x & 0x55) > 1;</p> <p>x = (x & 0x33) > 2;</p> <p>x = x >4; </p> <p>很短,但很清晰,它将左右的概念从细到粗一步一步地逼近问题的答案,就好像一个分形一样,没有终点,但聚集起来就是一个美丽的事物,活了,真的!</p> </strlen></p></length>