给定一个字符串,要求将字符串的前若干(m)位字符移动到字符串的尾部。
**例如**:将字符串"abcdef"的前3个字符'a'、'b'和'c'移到字符串的尾部,得到"defabc"。
n轮移动,每轮中将每个字符左移一位。
时间复杂度:O(mn); 空间复杂度:O(1)
void leftRotateString_1(string &str, int m)
{
if (m < 0) { // if m is negative, the modulus is implementation-defined
m += (-m / str.size() + 1) * str.size();
}
m %= str.size(); // m >= str.size(), shrink the value by multiple str.size()
for (int i = 0; i < m; ++i) { // shift left by one in every loop
char tmp = str[0]; // extra space O(1)
for (int j = 0; j < str.size() - 1; ++j) {
str[j] = str[j + 1];
}
str[str.size() - 1] = tmp;
}
}
将字符串分为两部分X("abc")、Y("def")。将源字符串全部反转后,XY两部分内容成功互换("fedcba"),但是X、Y内部也被反转;分别对X、Y内部进行反转后得到正确结果("defabc")。
时间复杂度:O(n); 空间复杂度:O(1),优化后为O(0)
void reverseString(string &str, int left, int right)
{
while (left < right) {
// swap two element by XOR operator to eliminate the extra space cost
str[left] ^= str[right] ^= str[left] ^= str[right];
++left;
--right;
}
}
void leftRotateString_2(string &str, int m)
{
if (m < 0) {
m += (-m / str.size() + 1) * str.size();
}
m %= str.size();
reverseString(str, 0, m - 1); // X segment with m characters
reverseString(str, m, str.size() - 1); // Y segment with n characters
reverseString(str, 0, str.size() - 1); // overall string
}
直接将元素循环左移m位;
具体的实现为:保存首个元素,将之后的第m个元素移动到当前位置。循环直到需要移动的元素为保存的元素;
类似于方法一种左移一位的过程,但是产生多个循环体的问题,即一轮循环后不是所有元素都被后移m位;
比如"abcdef",左移4位;一轮循环后为"efabcd",其中"ace"实现左移m位,而"bdf"保持原位;
解决方法:n个数移动m位,其中循环体的个数为n和m的最大公约数gcd,循环gcd趟得到结果(具体数学原理不知,实例演算一遍很容易得到答案)。
时间复杂度:O(n); 空间复杂度:O(1)。
相对于方法二,时间复杂度减少二分之一。因为方法二实际上每个元素移动两次,二方法三只移动一次。
int gcd(int a, int b) // the greatest common divisor
{
int rem;
while (b > 0) {
rem = a % b;
a = b;
b = rem;
}
return a;
}
void leftRotateString_3(string &str, int m)
{
if (m < 0) {
m += (-m / str.size() + 1) * str.size();
}
m %= str.size();
int pass = gcd(m, str.size());
for (int i = 0; i < pass; ++i) {
// in a loop, recursively shift left element by m interval
char tmp = str[i];
int j;
for (j = 0; j < str.size() / pass - 1; ++j) {
str[(i + j * m) % str.size()] = str[(i + j * m + m) % str.size()];
}
str[(i + j * m) % str.size()] = tmp;
}
}
#include
#include
using namespace std;
void leftRotateString_1(string &str, int m)
{
if (m < 0) { // if m is negative, the modulus is implementation-defined
m += (-m / str.size() + 1) * str.size();
}
m %= str.size(); // m >= str.size(), shrink the value by multiple str.size()
for (int i = 0; i < m; ++i) { // shift left by one in every loop
char tmp = str[0]; // extra space O(1)
for (int j = 0; j < str.size() - 1; ++j) {
str[j] = str[j + 1];
}
str[str.size() - 1] = tmp;
}
}
void reverseString(string &str, int left, int right)
{
while (left < right) {
// swap two element by XOR operator to eliminate the extra space cost
str[left] ^= str[right] ^= str[left] ^= str[right];
++left;
--right;
}
}
void leftRotateString_2(string &str, int m)
{
if (m < 0) {
m += (-m / str.size() + 1) * str.size();
}
m %= str.size();
reverseString(str, 0, m - 1); // X segment with m characters
reverseString(str, m, str.size() - 1); // Y segment with n characters
reverseString(str, 0, str.size() - 1); // overall string
}
int gcd(int a, int b) // the greatest common divisor
{
int rem;
while (b > 0) {
rem = a % b;
a = b;
b = rem;
}
return a;
}
void leftRotateString_3(string &str, int m)
{
if (m < 0) {
m += (-m / str.size() + 1) * str.size();
}
m %= str.size();
int pass = gcd(m, str.size());
for (int i = 0; i < pass; ++i) {
// in a loop, recursively shift left element by m interval
char tmp = str[i];
int j;
for (j = 0; j < str.size() / pass - 1; ++j) {
str[(i + j * m) % str.size()] = str[(i + j * m + m) % str.size()];
}
str[(i + j * m) % str.size()] = tmp;
}
}
int main()
{
string str = "abcdef";
leftRotateString_3(str, -2);
cout << str << endl;
return 0;
}
输入一个英文句子,反转句子中单词的顺序。例如,输入为"I am a student.",则输出"student. a am I"。
解法:类似解法二,将每个单词翻转,再将整个句子以字母为单位翻转。
#include
#include
using namespace std;
class Solution {
public:
string ReverseSentence(string str) {
if (str.length() == 0) {
return str;
}
// reverse every word
int i = 0, j = 0;
while (true) {
while (i < str.length() && str[i] == ' ') {
++i;
}
if (i == str.length()) {
break;
}
j = i;
while (j < str.length() && str[j] != ' ') {
++j;
}
reverseString(str, i, j - 1);
i = j;
}
// reverse overall sentence
reverseString(str, 0, str.length() - 1);
return str;
}
private:
void reverseString(string &str, int left, int right) {
while (left < right) {
str[left] ^= str[right] ^= str[left] ^= str[right];
++left;
--right;
}
}
};
int main()
{
Solution sol;
string str("I'm camel, not a camel.");
string ret = sol.ReverseSentence(str);
cout << ret << endl;
return 0;
}