1.1 旋转字符串
题目描述
给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b'移动到字符串的尾部,使得原字符串变成字符串“cdefab”。请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。
分析与解法
解法一:暴力移位法
解法二:三步反转法
举一反三
1、链表翻转。给出一个链表和一个数k,比如,链表为1→2→3→4→5→6,k=2,则翻转后2→1→6→5→4→3,若k=3,翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→6→5,用程序实现。
2、编写程序,在原字符串中把字符串尾部的m个字符移动到字符串的头部,要求:长度为n的字符串操作时间复杂度为O(n),空间复杂度为O(1)。 例如,原字符串为”Ilovebaofeng”,m=7,输出结果为:”baofengIlove”。
3、单词翻转。输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变,句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。例如,输入“I am a student.”,则输出“student. a am I”。
举一反三
1、链表翻转。给出一个链表和一个数k,比如,链表为1→2→3→4→5→6,k=2,则翻转后2→1→6→5→4→3,若k=3,翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→6→5,用程序实现。
#include "stdafx.h"
#include <iostream>
#include <vector>
//链表结点类型
struct List_Node
{
int m_num_;
List_Node *m_next_;
};
//尾插法创建一个单链表
void creat_list_from_tail(List_Node *&p_head)
{
std::cout << "尾插法创建一个单链表" << std::endl;
while (1)
{
//新建一个结点
List_Node *new_node = new List_Node;
std::cout << "please input a number: ";
std::cin >> new_node->m_num_;
new_node->m_next_ = NULL;
if (-1 == new_node->m_num_)
{
return;
}
if (NULL == p_head)//链表为空
{
p_head = new_node;
}
else
{
List_Node *p_cur = p_head;
while (p_cur->m_next_ != NULL)//找到最后一个结点
{
p_cur = p_cur->m_next_;
}
p_cur->m_next_ = new_node;
}
}
}
//头插法创建一个单链表
void creat_list_from_head(List_Node *&p_head)
{
std::cout << "头插法创建一个单链表" << std::endl;
while (1)
{
//新建一个结点
List_Node *new_node = new List_Node;
std::cout << "please input a number: ";
std::cin >> new_node->m_num_;
new_node->m_next_ = NULL;
if (-1 == new_node->m_num_)
{
return;
}
if (NULL == p_head)//链表为空
{
p_head = new_node;
}
else
{
new_node->m_next_ = p_head;
p_head = new_node;
}
}
}
//打印链表
void print_list(List_Node *p_head)
{
if (NULL == p_head)
{
std::cout << "链表为空!" << std::endl;
return;
}
List_Node *p_cur = p_head;
std::cout << "链表中的元素为:";
while (NULL != p_cur)
{
std::cout << p_cur->m_num_ << " ";
p_cur = p_cur->m_next_;
}
std::cout << std::endl;
}
//翻转链表
void reverse_list(List_Node *&list_head)
{
std::cout << "翻转链表!" << std::endl;
if (list_head == NULL)
{
std::cout << "链表为空!" << std::endl;
return;
}
List_Node *cur_node = list_head;//当前结点
List_Node *pre_node = NULL;//当前结点的前一个结点
List_Node *next_node = NULL;//当前结点的下一个结点
while (cur_node != NULL)
{
next_node = cur_node->m_next_;//记录当前结点的下一个结点
cur_node->m_next_ = pre_node;
pre_node = cur_node;
cur_node = next_node;
}
list_head = pre_node;
}
//将链表list_head按每k个元素切割成若干小的链表存放到list_vec中,且链表内部实现了翻转
void split_list(List_Node *&list_head, int &k, std::vector<list_node *=""> &list_vec)
{
List_Node *cur_node = list_head;//当前结点
List_Node *pre_node = NULL;//当前结点的前一个结点
List_Node *next_node = NULL;//当前结点的下一个结点
List_Node *list_tmp = NULL;
int count = k;
while (cur_node != NULL && count > 0)
{
--count;
next_node = cur_node->m_next_;//记录当前结点的下一个结点
cur_node->m_next_ = pre_node;
pre_node = cur_node;
cur_node = next_node;
if (count == 0 || cur_node == NULL)
{
count = k;
list_vec.push_back(pre_node);
pre_node = NULL;
}
}
}
//将若干小的链表链接成一个大的链表
void connect_list_vec(std::vector<list_node *=""> list_vec, List_Node *&list_head)
{
List_Node *cur_tail = NULL;
bool is_first = true;
for (std::vector<list_node *="">::iterator iter = list_vec.begin();
iter != list_vec.end(); ++iter)
{
if (is_first)
{
list_head = *iter;
cur_tail = *iter;
is_first = false;
}
else
{
cur_tail->m_next_ = *iter;
}
while (cur_tail->m_next_ != NULL)
{
cur_tail = cur_tail->m_next_;
}
}
}
//翻转链表,指定每K个元素翻转一次
void reverse_list(List_Node *list_head, int &k)
{
if (list_head == NULL)
{
std::cout << "链表为空!" << std::endl;
return;
}
std::cout << "翻转链表!" << std::endl;
while (1)
{
std::cout << "请输入一个数k: ";
std::cin >> k;
if (-1 == k)
{
return;
}
std::vector<list_node *=""> list_vec;
split_list(list_head, k, list_vec);
connect_list_vec(list_vec, list_head);
print_list(list_head);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
List_Node *list_head = NULL;
creat_list_from_tail(list_head);//创建链表
print_list(list_head);//打印链表
int k = 0;
reverse_list(list_head, k); //翻转链表
system("pause");
return 0;
}
2、编写程序,在原字符串中把字符串尾部的m个字符移动到字符串的头部,要求:长度为n的字符串操作时间复杂度为O(n),空间复杂度为O(1)。 例如,原字符串为”Ilovebaofeng”,m=7,输出结果为:”baofengIlove”。
#include <iostream>
#include <cstring>
#include <stdlib.h>
using namespace std;
void ReverseStr(char *s, int from, int to)
{
while(from < to)
{
char tp = s[from];
s[from++] = s[to];
s[to--] = tp;
}
}
void RightRotateStr(char *s, int n, int m)
{
m %= n;
ReverseStr(s, m, n - 1);
ReverseStr(s, 0, m - 1);
ReverseStr(s, 0, n - 1);
}
int main()
{
char a[80];
int m;
cin >> a;
cin >> m;
RightRotateStr(a, strlen(a), strlen(a) - m);
cout << a << endl;
system("pause");
return 0;
}
3、单词翻转。输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变,句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。例如,输入“I am a student.”,则输出“student. a am I”。
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
void ReverseStr(char *s, int from, int to)
{
while(from < to)
{
char tp = s[from];
s[from++] = s[to];
s[to--] = tp;
}
}
void ReveserWord(char *a)
{
int j = 0;
while(a[j] != '\0')
{
int i = j;
while(a[i] != ' ' && a[i] != '\0')
{
i++;
}
ReverseStr(a, j, i - 1);
j = i + 1;
}
}
int main()
{
char a[1024];
cin.getline(a,30);
ReverseStr(a,0,strlen(a) - 1);
ReveserWord(a);
cout << a << endl;
system("pause");
return 0;
}