2288. 价格减免

题目

给定一个字符串列表 sentence,表示一个句子,其中每个单词可以包含数字、小写字母和美元符号 $。如果单词的形式为美元符号后跟着一个非负实数,那么这个单词就表示一个价格。我们需要在价格的基础上减免给定的 discount%,并更新该单词到句子中。所有更新后的价格应该表示为一个恰好保留小数点后两位的数字。

示例

示例 1:

  • 输入: sentence = "there are $1 $2 and 5$ candies in the shop", discount = 50
  • 输出: "there are $0.50 $1.00 and 5$ candies in the shop"

示例 2:

  • 输入: sentence = "1 2 $3 4 $5 $6 7 8$ $9 $10$", discount = 100
  • 输出: "1 2 $0.00 4 $0.00 $0.00 7 8$ $0.00 $10$"

提示

  • 1 <= sentence.length <= 105
  • sentence 由小写英文字母、数字、’ ’ 和 ‘$’ 组成
  • sentence 不含前导和尾随空格
  • sentence 的所有单词都用单个空格分隔
  • 所有价格都是正整数且不含前导零
  • 所有价格最多为10位数字
  • 0 <= discount <= 100

解决方案

我们需要遍历整个句子,并检查每个单词是否是一个价格。如果是价格,则计算折扣后的新价格并替换原来的价格。以下是实现步骤:

  1. 遍历句子:使用指针遍历句子,查找每个价格单词。
  2. 判断是否为价格:判断单词是否以 $ 开头,且其后跟随的字符是数字。
  3. 计算折扣:对价格进行折扣计算,并格式化为保留两位小数。
  4. 构建新句子:将处理后的句子重新拼接起来。
    很烦,很多特殊处理,像上班处理需求一样。

代码实现

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

char* discountPrices(char* sentence, int discount) {
    size_t len = strlen(sentence);
    // 为结果分配足够大的内存,防止只有一个'$'+一位数的情况导致溢出
    char* result = malloc(len * 3);
    if (result == NULL) {
    	return NULL;
    }
    char* res_ptr = result;
    char* p = sentence;

    while (p < sentence + len) {
        // 查找下一个 '$' 符号
        char* price = strstr(p, "$");
        if (price) {
            // 将 '$' 之前的文本复制到结果中
            while (p < price) {
                *res_ptr++ = *p++;
            }

            // 检查 '$' 后的字符是否是数字
            if (price > sentence && *(price - 1) != ' ') {
                // 如果 '$' 前面的字符不是空格,将 '$' 复制到结果中并继续
                *res_ptr++ = *price++;
                p = price;
                continue;
            }

            if (!isdigit(*(price + 1))) {
                // 如果 '$' 后的字符不是数字,直接复制 '$' 并继续
                *res_ptr++ = *p++;
                continue;
            }

            // 提取并处理价格
            p = price + 1;
            double double_price = 0;
            char* end_of_price = p;
            while (isdigit(*end_of_price) || *end_of_price == '.') {
                end_of_price++;
            }

            // 检查价格是否紧跟非数字字符,如果是,则复制原始文本并继续
            if (*end_of_price != ' ' && *end_of_price != '\0') {
                while (price < end_of_price) {
                    *res_ptr++ = *price++;
                }
                p = end_of_price;
                continue;
            }

            char original_price[20] = {0};
            strncpy(original_price, price, end_of_price - price);
            original_price[end_of_price - price] = '\0'; // 将复制的字符串以 '\0' 结尾
            sscanf(original_price, "$%lf", &double_price);

            if (double_price == 0) {
                // 如果价格为 0,直接复制原始文本并继续
                p = end_of_price;
                while (*p && *p != ' ') {
                    *res_ptr++ = *p++;
                }
                continue;
            }

            // 计算折扣后的价格
            double_price *= (1 - discount / 100.0);

            // 格式化新的价格字符串
            char new_price[20] = {0};
            sprintf(new_price, "$%.2f", double_price);
            size_t new_price_len = strlen(new_price);

            // 将新的价格复制到结果缓冲区
            memcpy(res_ptr, new_price, new_price_len);
            res_ptr += new_price_len;

            p = end_of_price;
        } else {
            // 如果没有找到更多的价格,将剩余的文本复制到结果中
            while (*p) {
                *res_ptr++ = *p++;
            }
            break;
        }
    }
    *res_ptr = '\0';

    // 如果结果字符串长度小于等于原句子长度,将结果复制回原句子缓冲区
    if (strlen(result) <= len) {
        strcpy(sentence, result);
        free(result);
        return sentence;
    } else {
        // 如果结果过长,重新分配内存并返回新的缓冲区
        char* new_sentence = realloc(sentence, strlen(result) + 1);
        if (new_sentence == NULL) {
            printf("realloc failed");
            return NULL;
        }
        strcpy(new_sentence, result);
        free(result);
        return new_sentence;
    }
}

详细解析

  1. 内存分配

    • result 分配了 len * 3 的内存空间,以确保处理后的字符串有足够的空间存储。
  2. 查找价格单词

    • 使用 strstr 查找 $ 符号,判断其后是否跟随数字。
  3. 处理价格单词

    • 提取价格部分并进行折扣计算,结果保留两位小数。
    • 处理非价格部分的单词,直接复制到结果中。
  4. 字符串拼接

    • 将处理后的字符串拼接起来,并根据结果长度选择合适的缓冲区返回。

复杂度分析

  • 时间复杂度:O(n),其中 n 为字符串长度,需要遍历每个字符。
  • 空间复杂度:O(n),用于存储处理后的字符串。

结果

在这里插入图片描述

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值