算法练习-字符翻转

练习问题来源

https://wizardforcel.gitbooks.io/the-art-of-programming-by-july/content/01.01.html

 

要求:

给 定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b'移动到字符串的尾部,使得原 字符串变成字符串“cdefab”。请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。

解法:三步反转法
#include <stdio.h>
#include <stdlib.h>

// 把字符一个一个地移动到字符串的尾部
/*void LeftShiftOne(char* s, int n)
{
    char t = s[0];
    for (int i = 1; i < n; i++)
    {
        s[i-1] = s[i];
    }
    s[n-1] = t;
}

void LeftRotateString(char* s, int n, int m)
{
    while(m--)
    {
        LeftShiftOne(s, n);
    }
}*/ // 例如,字符串 abcdef ,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可: // 1. 首先将原字符串分为两个部分,即X:abc,Y:def; // 2. 将X反转,X->X^T,即得:abc->cba;将Y反转,Y->Y^T,即得:def->fed。 // 3. 反转上述步骤得到的结果字符串X^TY^T,即反转字符串cbafed的两部分(cba和fed)给予反转, // cbafed得到defabc,形式化表示为(X^TY^T)^T=YX,这就实现了整个反转。 void ReverseString(char* s, int from, int to) { char t; while(from < to) { t = s[from]; s[from++] = s[to]; s[to--] = t; } } void LeftRotateString(char* s, int n, int m) // 字符串长度 n, 翻转前 m 个 { m %= n; //若要左移动大于n位,那么和%n 是等价的 ReverseString(s, 0, m-1); ReverseString(s, m, n-1); ReverseString(s, 0, n-1); } void main() { char s[7] = {'s', 't', 'u', 'i', '4', '5', 'm'}; for (int i=0; i<7; i++) { printf("%c ", s[i]); } printf("\n"); LeftRotateString(s, 7, 4); for (int i=0; i<7; i++) { printf("%c ", s[i]); } }

 

相关练习

链表翻转。给出一个链表和一个数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。

/* List.h */
#ifndef _List_H
#define _List_H

struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;
typedef int ElementType;

List MakeEmpty(List L);
int IsEmpty(List L);
int IsLast(Position P, List L);
Position Find(ElementType X, List L);
void Delete(ElementType X, List L);
Position FindPrevious(ElementType X, List L);
void Insert(ElementType X, List L, Position P);
void DeletList(List L);

struct Node
{
    ElementType Element;
    Position Next;
};

#endif
List.h
/* List.cpp */
#include "List.h"
#include <stdlib.h>
#include <stdio.h>

// Return true if L is empty, 测试链表是否为空表
int IsEmpty(List L)
{
    return L->Next == NULL;
}

// Return true if P is the last position in list L
// Parameter L is unused in this implementation
// 测试当前位置是否是链表末尾
int IsLast(Position P, List L)
{
    return P->Next == NULL;
}

// Return Position of X in L; NULL if not found
Position Find(ElementType X, List L)
{
    Position P;
    P = L->Next;
    while(P != NULL && P->Element != X)
        P = P->Next;

    return P;
}

void Delete(ElementType X, List L)
{
    Position P, TmpCell;

    P = FindPrevious(X, L);

    if (!IsLast(P, L))
    {
        TmpCell = P->Next;
        P->Next = TmpCell->Next;  //P->Next->Next;
        free(TmpCell);
    }
}
Position FindPrevious(ElementType X, List L)
{
    Position P;

    P = L;
    while(P->Next != NULL && P->Next->Element != X)
        P = P->Next;

    return P;
}

// Insert (after legal position)
// Header implementation assumed
// Parameter L is unused in this implementation
void Insert(ElementType X, List L, Position P)
{
    Position TmpCell;

    TmpCell = (struct Node*)malloc(sizeof(struct Node));
    if (TmpCell == NULL)
        printf("Fatal Error: Out of space!!");

    TmpCell->Element = X;
    TmpCell->Next = P->Next;
    P->Next = TmpCell;
}

void DeleteList(List L)
{
    Position P, Tmp;

    P = L->Next;
    L->Next = NULL; // Header assumed
    while(P != NULL)
    {
        Tmp = P->Next;
        free(P);
        P = Tmp;
    }
}
List.cpp
#include <stdio.h>
#include <stdlib.h>
#include "List.h"
// 链表翻转:
// 给出一个链表和一个数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
void ListReverseFunc(List L, int k, int m)
{
    while (k < m)
    {
        int ikPos = 1;
        int imPos = 1;
        Position pkPos, pmPos;
        pkPos = L->Next;
        pmPos = L->Next;
        while(ikPos < k)
        {
            pkPos = pkPos->Next;
            ikPos++;
        }
        while(imPos < m)
        {
            pmPos = pmPos->Next;
            imPos++;
        }
        // 交换 k, m 位置的值
        pkPos->Element = pkPos->Element + pmPos->Element;
        pmPos->Element = pkPos->Element - pmPos->Element;
        pkPos->Element = pkPos->Element - pmPos->Element;

        k++;
        m--;
    }
}

void main()
{
    // 定义一个链表 ListReverse
    typedef PtrToNode List;
    List ListReverse;
    ListReverse = (struct Node*)malloc(sizeof(struct Node));

    // 对链表赋值 1, 2,..., 7
    Position P = ListReverse;
    for (int i = 1; i < 8; ++i)
    {
        P->Next = (struct Node*)malloc(sizeof(struct Node));
        Insert(i, ListReverse, P);
        P = P->Next;
    }
    P->Next = NULL; // 赋值结束, 链表尾部, 置空

    // k = 3, 反转链表
    int k = 5;
    ListReverseFunc(ListReverse, 1, k);
    ListReverseFunc(ListReverse, k+1, 7);

    // 输出翻转结果
    P = ListReverse->Next;
    while(!IsLast(P, ListReverse))
    {
        printf("%d, ", P->Element);
        P = P->Next;
    }
    printf("%d\n", P->Element);
  
    DeleteList(ListReverse); }

 

 

转载于:https://www.cnblogs.com/nobodyzhou/p/5459227.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值