【The-Art-Of-Programming】旋转字符串

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值