免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 4102 | 回复: 20
打印 上一主题 下一主题

[C] 旋转字符串,加了算法解释,求验证——总结:空间的处理,内、外空间都可以利用 [复制链接]

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-12-05 10:56 |只看该作者 |倒序浏览
本帖最后由 cokeboL 于 2018-07-28 18:46 编辑
  1. #include <cstdio>
  2. #include <string.h>

  3. int timeCount = 0;

  4. //len为需要转换的总长度,n是旋转的长度
  5. void str_turn_left(char *src, int len, int n)
  6. {
  7.         int i, end = len - 1;
  8.         char tmp;

  9.         n = n % len;
  10.         if(0 == (len * n))
  11.                 return;

  12.         while(end >= n - 1){
  13.                 for(i = n-1; i >= 0; i--, end--){
  14.                                                 timeCount++; //时间复杂度计数
  15.                         tmp = src[end];
  16.                         src[end] = src[i];
  17.                         src[i] = tmp;
  18.                 }
  19.         }
  20.         if((len % n) > 1)
  21.                 str_turn_left(src, len % n, n%(len % n));
  22. }


  23. int main()
  24. {
  25.         int i;

  26.         char a[15][20] =
  27.         {
  28.                 "a",
  29.                 "ab",
  30.                 "abc",
  31.                 "abcd",
  32.                 "abcde",
  33.                 "abcdef",
  34.                 "abcdefg",
  35.                 "abcdefgh",
  36.                 "abcdefghi",
  37.                 "abcdefghij",
  38.                 "abcdefghijk",
  39.                 "abcdefghijkl",
  40.                 "abcdefghijklm",
  41.                 "abcdefghijklmn",
  42.                 "abcdefghijklmno",
  43.         };

  44.         for(i = 0; i < sizeof(a)/sizeof(a[0]); i++){
  45.                 printf("%s ", a[i]);

  46.                 str_turn_left(a[i],strlen(a[i]),13);

  47.                 printf("-> %s\n", a[i]);
  48.                                 printf("timeCount: %d\n", timeCount);
  49.                                 timeCount = 0;
  50.         }

  51.         return 0;
  52. }
复制代码



解释下算法:


把字符串按照旋转的长度n分成几段,字符串头的前n个记为1,后面往前数依次为-1、-2,此图举例,到-3段时与1段有交叉;
算法依次按后续调换1段和-1段、1段和-2段、1段和-3段。。。类推;
每次调换-m段时-m段被放到1段的位置,下次和-(m-1)段调换,循环之后从后面数的段依次向前移动了n个字节,并且第一段在第一次调换时已经放在字符串尾部;
最后一次调换,就是第一段和图中-3段调换有交叉或者临界的情况,类似于memmove函数,由于是从后往前调换,可知交叉部分最后被放到了头部,交叉部分之前的部分被调换到了之后的位置,比如 "abcde",用后3个字符“cde”调换前3个字符“abc”之后,变成了“edabc”,这时需要再把'e'和'd'调换,就是旋转交叉部分前面的字符串;
通用的公式: 再次旋转的长度就是1段的长度减去交叉部分的长度,即strlen % n,旋转的位数就是交叉部分的长度,即 n % (len % n),当len % n <= 1时不交叉或者为单字符,不需要旋转,详见代码

总的来讲,用一个字节进行段的替换,使字符串开头的段成了临时的buf用来存储下次需要调换的字节,这样用1个字节+自身空间实现,节省了单独开辟buf的内存,使空间复杂度为O(1)go,如果不可以,那就随意吧,如果不是cpu消耗型的,性能问题不大,如果用5.1的话可以把luajit搞上比lua快很多

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
2 [报告]
发表于 2012-12-05 11:03 |只看该作者
本帖最后由 cokeboL 于 2012-12-05 11:19 编辑

有效代码15行左右,还算俭省;
加打印计算循环次数基本都是  小于等于 strlen,不知道可不可以算时间复杂度为O(<=n);
循环内的操作,看上去是每次swap交换比较浪费,但实际就相当于几次赋值,与之前那两种经典算法中给下标赋值或者reverse等操作相比,并不浪费;
验证了几个旋转长度1、2、3、5、6、7、13等,目测应该是正确的,但还不敢保证全对;
求各位帮忙验证一下。
那两种经典算法参考:
http://www.cnblogs.com/jy02414216/archive/2012/08/10/2633041.html

论坛徽章:
154
2022北京冬奥会纪念版徽章
日期:2015-08-07 17:10:5720周年集字徽章-年
日期:2022-10-26 16:44:2015-16赛季CBA联赛之深圳
日期:2022-11-02 14:02:4515-16赛季CBA联赛之八一
日期:2022-11-28 12:07:4820周年集字徽章-20	
日期:2023-07-19 08:49:4515-16赛季CBA联赛之八一
日期:2023-11-04 19:23:5115-16赛季CBA联赛之广夏
日期:2023-12-13 18:09:34
3 [报告]
发表于 2012-12-05 12:14 |只看该作者
毕业多年了,一把老骨头了,很少写工作不实用的代码了


google snprintf
这个库函数可是我第一家公司学来的三大利器之一哦{:3_188:}

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
4 [报告]
发表于 2012-12-05 12:39 |只看该作者
回复 3# shang2010


简单的字符串操作,何必用snprintf。。。

这个是实现时间O(n)空间O(1)的。。。工作确实不用,只是最近闲的无聊,才玩玩的

论坛徽章:
3
寅虎
日期:2013-11-27 07:53:29申猴
日期:2014-09-12 09:24:152015年迎新春徽章
日期:2015-03-04 09:48:31
5 [报告]
发表于 2012-12-05 13:05 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
6 [报告]
发表于 2012-12-05 13:27 |只看该作者
回复 5# Sevk


我写这个的初衷是基于之前小乔那个帖子
http://bbs.chinaunix.net/thread-4056843-1-1.html

只考虑O(n) + O(1)情况的算法,两行代码差不多搞定的写法大部分人都懂但是空间做不到O(1)

论坛徽章:
0
7 [报告]
发表于 2012-12-05 13:29 |只看该作者
看这代码感觉费劲,你们是怎么炼就出来的!

论坛徽章:
3
寅虎
日期:2013-11-27 07:53:29申猴
日期:2014-09-12 09:24:152015年迎新春徽章
日期:2015-03-04 09:48:31
8 [报告]
发表于 2012-12-05 13:33 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
9 [报告]
发表于 2012-12-05 15:04 |只看该作者
本帖最后由 sacry 于 2012-12-05 17:15 编辑

@@

代码删除

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
10 [报告]
发表于 2012-12-05 15:13 |只看该作者
回复 9# sacry


    这不就是公约数那个吗,链接里有,我写的是新的,跟那两种不同的,求PK的版本
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP