您的位置:首页 > 其它

算法——从旋转字符串到翻转单词

2016-03-20 23:00 176 查看

一、字符串的旋转

描述:给定一个字符串,要求将字符串前面的若干字符移到字符串的末尾。例如,将字符串的 “abcdef” 的前面 3 个字符 ‘a’, ‘b’ ‘c’ 移到字符串的末尾,那么原字符串将变成 “defabc”。

解法一:蛮力移位(循环左移)

较为直观的一种解法即是,将需要移动的字符使用循环左移(ROL,Ring Shift Left)的方式一个一个地移到字符串的尾部。

// 循环左移 1 位,循环左移k位的辅助函数
void ROL1(char* s, int n)
{
char t = s[0];
for (int i = 1; i < n; ++i)
s[i-1] = s[i];
s[n-1] = s[0];
}
// 循环左移 k 位
void ROLK(char* s, int n, int k)
{
while (k--)                       // while (--k) 会比 while (k--) 少做一次循环
ROL1(s, n);
}


时间复杂度分析:对于长度为 n 的字符串,如果左移 m 位的话,时间复杂度为 O(mn).

解法二:三步反转

这是一个稍具 Tricky 的解法,且解法具有普世性,句子中单词的翻转,即可使用该解法解决:

(1)将源字符串分为 X 和 Y 两部分,其中 X 为 “abc”,Y 为 “def”

(2)翻转 X,翻转 Y,X ⇒ “cba”,Y ⇒ “fed”

(3)整体翻转,”cbafed” ⇒ “defabc”

// 辅助函数
void ReverseString(char* s, int from, int to)
{
while (from  < to)
{
char t = s[from];
s[from++] = s[to];
s[to--] = t;
}
}

// 三步反转
void LeftRotateString(char* s, int n, int m)
{
m %= n;
ReverseString(s, 0, m-1);
ReverseString(s, m, n-1);
ReverseString(s, 0, n-1);
}


时间复杂度为:O(n)

二、单词的翻转

输入一个英文句子,翻转句子中单词的顺序,要求单词内字符的顺序不变,句子中单词以空格符隔开。为简单起见,标点符号和普通字母做同样处理。

“I am a student.” ⇒ “student. a am I”

沿用“三步反转”法的思路,先将每个单词自翻转,再整体翻转,求解的难点在于,每个单词的确定,我们使用数组索引的方式确定每个单词的起始和截止。

void ReverseWords(char* s, int n)
{
int arr[255] = { 0 };
int idx = 0;
for (int i = 0; i < n; ++i)
{
if (s[i] == ' ')
arr[idx++] = i;
}
idx -= 1;
ReverseString(s, 0, arr[0]-1);
for (int i = 0; i < idx; ++i)
{
ReverseString(s, arr[i]+1, arr[i + 1]-1);
}
ReverseString(s, arr[idx] + 1, n-1);
ReverseString(s, 0, n - 1);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: