携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
一、题目描述:
给定一个许可密钥字符串 s
,仅由字母、数字字符和破折号组成。字符串由 n
个破折号分成 n + 1
组。你也会得到一个整数 k
。
我们想要重新格式化字符串 s
,使每一组包含 k
个字符,除了第一组,它可以比 k
短,但仍然必须包含至少一个字符。此外,两组之间必须插入破折号,并且应该将所有小写字母转换为大写字母。
返回 重新格式化的许可密钥 。
示例 1:
输入:S = "5F3Z-2e-9-w", k = 4
输出:"5F3Z-2E9W"
解释:字符串 S 被分成了两个部分,每部分 4 个字符;
注意,两个额外的破折号需要删掉。
示例 2:
输入:S = "2-5g-3-J", k = 2
输出:"2-5G-3J"
解释:字符串 S 被分成了 3 个部分,按照前面的规则描述,第一部分的字符可以少于给定的数量,其余部分皆为 2 个字符。
提示:
- 1 <= s.length <= 10^5
- s 只包含字母、数字和破折号 '-'.
- 1 <= k <= 10^4
二、思路分析:
技巧 两个栈,倒腾一下
- 所有字符入栈
- 所有字符出栈,然后入新栈,每K个字符填加一个‘-’
- 新栈出栈到字符串
- 返回
如果没有有效字符,返回的是“”不是NULL
要求的各式是从倒数第一组到正数第二组,每组都是K个字符,第一组不必是K个字符。
而不是说,第一组和原字符串中的第一组一样,剩下的组都是K个字符,到最后一组凑不出K个字符的话就有几个写几个。
三、AC 代码:
//--------------------------------------------------------------链表栈
typedef struct Node
{
char data;
struct Node* next;
}Node;
Node* newNode(char Data)
{
Node* n=(Node*)malloc(sizeof(Node));
n->data=Data;
n->next=0;
return n;
}
void push(Node* Head,char Data)
{
Node* n=newNode(Data);
n->next=Head->next;
Head->next=n;
}
char pop(Node* Head)
{
Node* n=Head->next;
Head->next=n->next;
int result= n->data<'a'? n->data : n->data-('a'-'A');
free(n);
return result;
}
int length(Node* Head)
{
int result=0;
while(Head->next!=0)
{
++result;
Head=Head->next;
}
return result;
}
void del(Node* Head)
{
while(Head!=0)
{
Node* n=Head;
Head=Head->next;
free(n);
}
}
//--------------------------------------------------------------解答
char * licenseKeyFormatting(char * S, int K){
//所有有效字符入栈,如果没有有效字符,直接返回 ""
Node* stack=newNode('\0');
while(*S!='\0')
{
if(*S!='-')
push(stack,*S);
++S;
}
if(stack->next==0)
{
del(stack);
return "";
}
//字符出栈之后进入新栈,每K个字符添加一个‘-’
Node* resultStack=newNode('\0');
for(int i=0;stack->next!=0;i=(i+1)%K)
{
if(i==0)
push(resultStack,'-');
push(resultStack,pop(stack));
}
//新栈出栈到字符串
int l=length(resultStack);
char* result=(char*)malloc(sizeof(char)*l);
for(int i=0;i<l;++i)
result[i]=pop(resultStack);
result[l-1]='\0';
//释放栈空间、返回结果
del(stack);
del(resultStack);
return result;
}