leetcode每日一题

目录

🏆重新格式化电话号码

👓①麻烦解法

👓②使用库函数降维打击

每日鸡汤:

                🚀有志者自有千计万计,无志者只感千难万难。

🏆重新格式化电话号码

给你一个字符串形式的电话号码 number 。number 由数字、空格 ' '、和破折号 '-' 组成。

请你按下述方式重新格式化电话号码。

首先,删除 所有的空格和破折号。
其次,将数组从左到右 每 3 个一组 分块,直到 剩下 4 个或更少数字。剩下的数字将按下述规定再分块:
2 个数字:单个含 2 个数字的块。
3 个数字:单个含 3 个数字的块。
4 个数字:两个分别含 2 个数字的块。
最后用破折号将这些块连接起来。注意,重新格式化过程中 不应该 生成仅含 1 个数字的块,并且 最多 生成两个含 2 个数字的块。

返回格式化后的电话号码。

通读一遍,要求很明确,每三个当作一组,然后破折号分开当最后剩4个的时候,需要两两一组,少于4个的时候当作一组即可

这道题目的解法也很普通,遍历一遍,设新的数组去存储这些数字字符。然后我们需要malloc一个新的数组当作最后的返回数组。平平无奇,但是我想说的是,如果这道题目不妥善处理,将会很麻烦。

👓①麻烦解法

如果不使用库函数去简化代码,将很辛苦,博主第一次做的时候就是暴力遍历数字字符数组,用两个变量计算两种情况需要多少个破折号

1、第一种情况每三个数字字符为一组,用一个变量timesOf3记录有多少个破折号——,它记录的破折号用于隔离每三个数字字符,但是这里有个细节:

timesOf2记录当剩余小于等于4个字符时需要多少个破折号,比如剩余4个就需要2个破折号

 2、比较麻烦的是,我并没有使用库函数去简化代码,而是用创建变量标记,记录当每遍历到3个时,就在循环里特殊处理一下加一下‘——’。然后还需要考虑特殊情况,非常麻烦。

说明:可能有的老铁觉得为什么要计算破折号的个数,直接作减去做这道题目不是舒服点嘛,我给老铁说明一下,直接作减确实比较方便,但是我们不知道要返回的数字字符数组多大空间啊,博主主要想通过计算破折号加上原有长度当然别忘记'\0',就能精确计算到底需要多少空间,不至于空间浪费。(但事实证明大部分oj题给大点空间(一般两倍)都可以通过,有点没必要浪费代码去做这个工作😂)

char * reformatNumber(char * number)
{
    int length=strlen(number);
    char tmp[length];
    int count=0;
    for(int i=0;i<length;++i)
    {
        if(number[i]!='-'&&number[i]!=' ')
            tmp[count++]=number[i];
    }
    //计算需要多少破折号
    int m=0;
    if(count==4)
    {
        char* ret=(char*)realloc(number,sizeof(char)*7);
        if(ret==NULL)
        {
            perror("realloc fail");
            exit(-1);
        }
        number=ret;
        int time=0;
        for(int i=0;i<count;++i)
        {
            if(time==2)
            {
                number[m++]='-';
                i--;
                time=0;
            }
            else
            {
                number[m++]=tmp[i];
                time++;
            }
        }
    }
    else
    {
        int timesOf3=count/3;//这里其实多了一个,后面剪去
        int timesOf2=0;
        if(count-timesOf3*3==1)
        {
            //说明剩余了4
            timesOf3-=2;//需要少一个
            timesOf2=2;
        }
        else if(count-timesOf3*3==2)
        {
            timesOf3-=1;
            timesOf2=1;
        }
        else
        {
            timesOf3-=1;
        }
        char* ret=(char*)realloc(number,sizeof(char)*(timesOf3+timesOf2+count+1));
        if(ret==NULL)
        {
            perror("realloc fail");
            exit(-1);
        }
        number=ret;
        int time=0;
        int i=0;
        for(i=0;i<count;++i)
        {
            if((count-i==4&&timesOf3==0&&timesOf2==2)
            ||(count-i==2&&timesOf3==0&&timesOf2==1))
                break;
            if(time==3&&timesOf3>0)
            {
                number[m++]='-';
                timesOf3--;
                i--;
                time=0;
            }
            else
            {
                number[m++]=tmp[i];
                time++;
            }
        }
        time=2;
        while(i<count)
        {
            if(time==2&&timesOf2>0)
            {
                number[m++]='-';
                timesOf2--;
                time=0;
            }
            else
            {
                number[m++]=tmp[i++];
                time++;
            }
        }
        }
     number[m]='\0';
     return number;

}

时间复杂度:O(n)

空间复杂度:O(n)

👓②使用库函数降维打击

1、这道题目如果去使用库函数strncpy 

 是非常契合题目的。它可以拷贝指定大小的内容到目标空间。非常好用。这里还使用了一个库函数isdigit---int isdigit(int c) 检查所传的字符是否是十进制数字字符

2、还可以简化的地方是,不要去计算3个为一组需要多少个破折号,剩余的小于等于四个数字字符需要多少个破折号。而是不断作减法,每拷贝3个数字字符,数字字符个数减3,加破折号,当小于等于4个时就特别处理一下

char * reformatNumber(char * number)
{
    int length=strlen(number);
    char digits[length+1];
    int pos=0;
    for(int i=0;i<length;++i)
    {
        char ch=number[i];
        if(isdigit(ch))
        {
            //是数字字符就存下来
            digits[pos++]=ch;
        }
    }
    int n=pos;//存一下数字字符个数
    //开辟空间--比较粗暴,其实可以计算
    char *ret=(char*)malloc(sizeof(char)*n*2);
    pos=0;
    int pt=0;
    while(n)
    {
        if(n>4)
        {
            strncpy(ret+pos,digits+pt,3);
            pos+=3;
            ret[pos++]='-';
            pt+=3;
            n-=3;
        }
        else
        {
            if(n==4)
            {
                strncpy(ret+pos,digits+pt,2);
                pos+=2;
                ret[pos++]='-';
                pt+=2;
                strncpy(ret+pos,digits+pt,2);
                pos+=2;
            }
            else
            {
                strncpy(ret+pos,digits+pt,n);
                pos+=n;
            }
            break;
        }
    }
    ret[pos]='\0';
    return ret;

}

 时间复杂度:O(N)

空间复杂度:O(N)

这道题目,其实并不难,只是提醒我们在做oj题,能使用库函数去简化,我们尽量调用库函数,也能增进我们对库函数的掌握。如果不知道用什么库函数,就看一下答案,学习优秀代码咯🚀。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值