一道有趣的面试题

题目大意:给你一个由小写字母和*符号组成的字符串,要求你把其中的*符号全部转移到字符串的首部,而其他字母的相对序列保持不变,如*af*dxc*aa*转换成****afdxcaa。要求时间复杂度和空间复杂度尽量小。(其实这个问题还有好多变种,比如将一个字符串的大写字母转移到字符串前面或后面,将一个数组中的奇数和偶数区分开来,前半部分为偶数后半部分为奇数等等)

 

思路:这里介绍一个时间复杂度为O(n),空间复杂度为O(1)的方法。我们设两个变量,x表示最右边的*符号的位置,y表示在x左边的最右边的小写字母的位置。那么首先从右到左将第一个x和y求出来,然后交换两个位置的字符,交换之后继续从右到左更新x和y的值,当x或y小于0时退出,这个算法空间复杂度显然为O(1),下面来看时间复杂度,由于x和y一直是递减的,从n-1减到0为止,所以时间复杂度为O(n)。至于算法为什么是正确的,自己推一下就明白了,这道题还是看得蛮多的,好多公司面试都有,还有好多变种,但是思想是相同的。详细实现请看代码:

代码如下:

#include <stdio.h>
#include <string.h>
#define maxn 110
void solve(char *str)
{
    int len=strlen(str),x,y;
    x=len-1;
    while(x>=0&&str[x]!='*')
    x--;
    y=x-1;
    while(y>=0&&str[y]=='*')
    y--;
    while(x>=0&&y>=0)
    {
        str[x]=str[x]^str[y];
        str[y]=str[x]^str[y];
        str[x]=str[x]^str[y];
        //以上是交换两个字符
        while(x>=0&&str[x]!='*')
        x--;
        while(y>=0&&str[y]=='*')
        y--;
    }
}
int main()
{
    char str[maxn];
    scanf("%s",str);
    solve(str);
    printf("%s\n",str);
    return 0;
}


 

你可能感兴趣的:(一道有趣的面试题)