左旋字符串的一种野路子解法,时间复杂度O(2N)
来源:互联网 发布:linux退出vi模式 编辑:程序博客网 时间:2024/04/30 03:39
* 题目:定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。
* 如把字符串abcdef左旋转2位得到字符串cdefab。
* 如把字符串abcdef左旋转2位得到字符串cdefab。
* 请实现字符串左旋转的函数。要求时间对长度为n的字符串操作的复杂度为O(n),辅助内存为O(1)。
据说是微软面试题,想挑战一把自己,于是不看答案闷头想了两天,得到一次优解-_-!
题目可抽象成:数组由
1 2 3 ... N ... L
到
N+1 N+2 .... L 1 2 3 ... N
的变化
由于空间复杂度为O(1),所以不能开辟arr_new,并让arr_new[i] = arr_old[(i+N+1)%L]
又由于时间复杂度为O(N),所以不能定义函数leftTurn1elem(),再循环调用N次,这就变成O(N^2)了
所以必须是某种swap,一步到位的swap,但又不能是对等的swap,而是麻花债式的swap,就是a要占b的空间,b转而去占c的空间,以此类推
那怎么保证麻花债的终止呢?我想了很多办法,最终决定用flag,表示该元素的空间已被侵占了,不用再去讨债了。
有人要问,每个数组元素配一个flag,空间占用还是O(N)啊!问得好,我这里用了个trick,将每个字符的最高位(ASCII用不到)当做flag。
最后,怎么保证N个元素都迁移了呢?用for循环,每个元素都apply上述步骤,对于N > L/2的情况,会出现前一轮麻花债影响后一轮的情况,好办,for循环也检测是否已侵占,若是则continue跳过。
#include <iostream>#include <cstring>using namespace std;bool Visited(char *a){ return (((*a & 0x80) != 0) ? true : false);}void Visit(char *a){ *a = *a | 0x80;}void deVisit(char *a){ *a = *a & 0x7f;}void leftturn(char *p, int len, int turn){ if (turn < 1 || turn > len) { cout << "wrong input" << endl; return; } char tmpSave, tmpRestore; int srcPos, dstPos; bool firstVisit; for (int c = 0; c < turn; c++) { if (Visited(&p[c])) continue; srcPos = c; firstVisit = true; while(1){ dstPos = srcPos - turn < 0 ? srcPos - turn + len : srcPos - turn; if (Visited(&p[dstPos])) break; tmpSave = p[dstPos]; if (firstVisit) { p[dstPos] = p[srcPos]; firstVisit = false; }else{ p[dstPos] = tmpRestore; } Visit(&p[dstPos]); srcPos = dstPos; tmpRestore = tmpSave; } } for (int i = 0; i < len; i++) deVisit(&p[i]);}char a[] = "wanghaipeng";int main(){ cout << a << endl; leftturn(a, strlen(a), 2); cout << a << endl; return 0;}
0 0
- 左旋字符串的一种野路子解法,时间复杂度O(2N)
- 字符串左旋满足时间复杂度为O(n)
- 字符串移动k位的时间复杂度o(n)空间复杂度o(1)的解法
- 【算法】字符串左移函数的O(n)解法
- 将m,n(m>n)的连续自然数序列,打乱顺序重新排列,随机取出一个数,试问取出的这个数是多少?使用一种解法,时间复杂度O(m-n),空间复杂度O(1)
- 约瑟夫环时间复杂度O(n)解法
- 实现左移指定位数,时间复杂度O(n) ,空间复杂度O(1)
- 约瑟夫环O(n)复杂度的解法
- leetCode & hihocoder:最长回文子字符串时间复杂度为O(N)解法
- leetCode & hihocoder:最长回文子字符串时间复杂度为O(N)解法
- 数组中只出现一次的数字,时间复杂度O(n),空间复杂度O(1)的解法
- O(n)时间复杂度旋转字符串
- Leetcode 234 Palindrome Linked List 复杂度为时间O(n) 和空间(1)解法
- 青蛙跳台阶解法 时间复杂度O(n) 空间复杂度O(1)
- 时间复杂度O(n),空间复杂度O(1)的排序
- 使用O(n)的时间复杂度合并两个数组
- 关于中位数的时间复杂度为什么是O(n)
- 时间复杂度为O(n)的排序
- dddd
- Michael Kors Handtassen a fself-help guide toshionistshopping online's
- Michael Kors Jet Set you can still split an fur to learn how doing this television for computer wher
- Linux -- logrotate 切割 Nginx
- 贝塞尔曲线
- 左旋字符串的一种野路子解法,时间复杂度O(2N)
- 触发器详解
- 黑马程序员——类的本质
- 《unix高级环境编程》终端 I/O——终端 IO 基本概述
- 叠片过滤器:怎样解决输油管和过滤器堵塞问题
- 叠片过滤器:过滤器设备的普遍使用
- 对象继承机制
- thinkphp中的查询技巧总结
- C#获得刚刚插入记录的自增ID