• Programming Pearls 笔记2


    关于旋转字符串和回文

    这个断断续续看了好长时间。

    书中给了三种旋转字符串的方法

    1.juggling

    这个方法比较巧妙。

    过程就是:假设x[] = “abcdefgh" 长度为8   从第3位开始。   即 n=8 ,i=3

    执行下列交换

    x[0]与x[0+i%n]  

    x[0+i%n]与 x[0+2*i%n]   ……

    每次都要模n.

    一直到  再回到 x[0]为止。    即k*i%n==0的时候

    注意:

    如果没有完成全部交换,第二次就从x[1]开始   然后是,  x[1+i],x[1+2i]......

    还是要模n.

    整个过程进行     i和n  的最大公约数次     就可以完成字符串的旋转。     (why?  此处没想通)

    这个问题,我至今没有想明白。。。。。

    不知道 ,我把整个过程说清楚没有。。  我个人觉得原书上也没有说太清楚,可能自己英文水平还不够吧,自己琢磨好久才写代码来。

    没看明白,即看代码吧。看过代码就清楚了。

    自己实现的代码如下:

     1 void juggling (int i,int n,char *x)
    2 {
    3 int cycles=gcd(i,n);//最大公约数
    4 int t;
    5 for(int j=0;j<cycles;j++)
    6 {
    7 t=x[j];
    8 int k=j;
    9 do
    10 {
    11 x[k%n]=x[(k+i)%n];
    12 k+=i;
    13 }while(k%n!=j);
    14 x[(k-i)%n]=t;
    15 }
    16 }


    对比作者给出的代码如下:

     1 void jugglerot(int rotdist, int n)
    2 { int cycles, i, j, k, t;
    3 cycles = gcd(rotdist, n);
    4 for (i = 0; i < cycles; i++) {
    5 /* move i-th values of blocks */
    6 t = x[i];
    7 j = i;
    8 for (;;) {
    9 k = j + rotdist;
    10 if (k >= n)
    11 k -= n;
    12 if (k == i)
    13 break;
    14 x[j] = x[k];
    15 j = k;
    16 }
    17 x[j] = t;
    18 }
    19 }
    20
    21 void jugglerot2(int rotdist, int n)
    22 { int cycles, i, j, k, t;
    23 cycles = gcd(rotdist, n);
    24 for (i = 0; i < cycles; i++) {
    25 /* move i-th values of blocks */
    26 t = x[i];
    27 j = i;
    28 for (;;) {
    29 /* Replace with mod below
    30 k = j + rotdist;
    31 if (k >= n)
    32 k -= n;
    33 */
    34 k = (j + rotdist) % n;
    35 if (k == i)
    36 break;
    37 x[j] = x[k];
    38 j = k;
    39 }
    40 x[j] = t;
    41 }
    42 }

    2.块交换

    这个方法的过程就是:

    让 ab ==> ba  

    先  a1a2b  (a1=b)    ==>   ba2a1  

    然后想办法   a2a1  ==>   a1a2    明显递归进行就可以了。

    这个方法本来想自己写出递归的程序。

    然后是怎么也没写出来,不知道怎么控制条件

    分析作者给出的代码。 

    在某位网友的指点下,终于弄明白怎么回事情了。

     1 void gcdrot(int rotdist, int n)
    2 { int i, j, p;
    3 if (rotdist == 0 || rotdist == n)
    4 return;
    5 i = p = rotdist;
    6 j = n - p;
    7 while (i != j) {
    8 /* invariant:
    9 x[0 ..p-i ] is in final position
    10 x[p-i..p-1 ] = a (to be swapped with b)
    11 x[p ..p+j-1] = b (to be swapped with a)
    12 x[p+j..n-1 ] in final position
    13 */
    14 if (i > j) {
    15 swap(p-i, p, j);
    16 i -= j;
    17 } else {
    18 swap(p-i, p+j-i, i);
    19 j -= i;
    20 }
    21 }
    22 swap(p-i, p, i);
    23 }
    24 /*这段代码里面。 i 和 j 始终代表 每次旋转 左边 和右边 字符串长度。 例如 abc|de i=3 j=2。 然后p 初始值为i 的初始值。
    25 是为了 swap的时候定位。 最后,i 和 j 只能是 1 和 1 */
    26
    27 交换的代码如下:
    28 void swap(int i, int j, int k) /* swap x[i..i+k-1] with x[j..j+k-1] */
    29 { int t;
    30 while (k-- > 0) {
    31 t = x[i]; x[i] = x[j]; x[j] = t;
    32 i++;
    33 j++;
    34 }
    35
    36 }
    37 /*交换的时候也可以用 a=a+b;b=a-b;a=a-b的原理去做,效率更高*/

    开始看。。完全不知道  i j p 是什么意思。。

    但还是没有把它改成 递归的形式。。    功力还是不够啊。。

    3.reverse

    这个方法就比前面的 简单明了多了。。

    原理就是:  ab ==>  ba

      1    arb

      2    arbr

      3    (arbr)r

    这样就行了。

    void reverse(int i,int j)
    {
    int t;
    for(;i<j;)
    {
    t=x[i];x[i]=x[j];x[j]=t;
    i++;
    j--;
    }
    }
    void swap(int i,int n)
    {
    reverse(0,i-1);//cbadefgh
    reverse(i,n-1);//cbahgfed
    reverse(0,n-1);//defghabc
    }


    简洁,明了。

    还有一个思想就是回文。

    快速找出回文词。

    思路就是:

    每个单词 打乱原来的顺序  

    按照字母顺序重排  作为原来的sign

    这样,只要是回文,就有同样的sign。

    根据相同的sign   输出回文 就行了。

    stop  tops  pots   都有相同的sign    "opst"

    今天就到此吧。

    读这种书真的很费劲。

    坚持!

  • 相关阅读:
    岗位要求与人才匹配
    http://blog.csdn.net/wujunokay/article/details/44783383
    好单位与坏单位
    工作那些事(三十四)杂记
    工作那些事(三十三)面试官的感想和建议
    工作那些事(三十二)由孙悟空的两个故事谈个人与团队
    工作那些事(三十一)如何带好一个项目团队
    工作那些事(三十)如何提升个人能力
    工作那些事(二十九)团队建设和人才招聘
    工作那些事(二十八)项目管理模式:项目型、职能型、矩阵型
  • 原文地址:https://www.cnblogs.com/xibaohe/p/2419681.html
Copyright © 2020-2023  润新知