leetcode每日一题

简介: leetcode每日一题

🏆重新格式化电话号码


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


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


首先,删除 所有的空格和破折号。

其次,将数组从左到右 每 3 个一组 分块,直到 剩下 4 个或更少数字。剩下的数字将按下述规定再分块:

2 个数字:单个含 2 个数字的块。

3 个数字:单个含 3 个数字的块。

4 个数字:两个分别含 2 个数字的块。

最后用破折号将这些块连接起来。注意,重新格式化过程中 不应该 生成仅含 1 个数字的块,并且 最多 生成两个含 2 个数字的块。


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


1669267627754.jpg


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


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


👓①麻烦解法


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


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


1669267642370.jpg


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

1669267650265.jpg

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


1669267678984.jpg


是非常契合题目的。它可以拷贝指定大小的内容到目标空间。非常好用。这里还使用了一个库函数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题,能使用库函数去简化,我们尽量调用库函数,也能增进我们对库函数的掌握。如果不知道用什么库函数,就看一下答案,学习优秀代码咯🚀。

相关文章
|
7月前
|
索引
leetcode每日一题刷题打卡1700
leetcode每日一题刷题打卡1700
53 0
|
6月前
|
索引
力扣每日一题 5/25
力扣每日一题 5/25
38 2
|
2月前
【LeetCode-每日一题】移动零
【LeetCode-每日一题】移动零
29 1
|
6月前
|
存储
力扣每日一题 6/9
力扣每日一题 6/9
45 5
|
6月前
|
存储 人工智能 算法
力扣每日一题 6/4
力扣每日一题 6/4
38 3
LeetCode】每日一题(4)
LeetCode】每日一题(4)
46 0
【LeetCode】每日一题(3)
【LeetCode】每日一题(3)
67 0
|
算法 C语言 索引
每日一题:LeetCode-283. 移动零
每日一题:LeetCode-283. 移动零
|
存储 Java
力扣-每日一题
给你一个 32 位的有符号整数 x ,返回 x 中每位上的数字反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。 假设环境
50 0
【LeetCode】每日一题(5)
【LeetCode】每日一题(5)
56 0