每日练习——leetcode402. 移掉 K 位数字和17. 电话号码的字母组合

目录

402. 移掉 K 位数字

题目描述

解题思路

代码实现

17. 电话号码的字母组合

题目描述

解题思路

代码实现


402. 移掉 K 位数字

题目描述

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

示例 1 :

输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

示例 2 :

输入:num = "10200", k = 1
输出:"200"
解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

示例 3 :

输入:num = "10", k = 2
输出:"0"
解释:从原数字移除所有的数字,剩余为空就是 0 。

提示:

  • 1 <= k <= num.length <= 105
  • num 仅由若干位数字(0 - 9)组成
  • 除了 0 本身之外,num 不含任何前导零

解题思路

利用单调栈的思想来移除字符串中的k个数字,使得剩下的数字组成的数最小。

  1. 初始化:

    • 获取输入字符串num的长度length
    • 初始化一个栈stack,用于存放结果。栈的大小为length + 1,因为最后还需要存放一个字符串结束符\0
    • 初始化栈顶指针top为-1,表示栈为空。
    • 初始化遍历索引i为0。
  2. 遍历输入字符串:

    • 对于输入字符串中的每个字符,进行以下操作:
      • 如果栈不为空且栈顶元素大于当前字符,并且还有剩余要移除的字符数k,那么将栈顶元素弹出,同时k减1。这一步是为了确保栈内的元素是单调递增的,这样可以确保得到的数最小。
      • 如果当前字符不是'0'或者栈不为空,那么将当前字符压入栈中。这里有一个条件判断是为了避免在结果的最前面出现前导零。
  3. 处理剩余的移除次数:

    • 如果遍历完输入字符串后还有剩余的移除次数k,那么继续从栈顶弹出元素,直到移除次数用完或者栈为空。
  4. 处理特殊情况:

    • 如果栈为空(即所有字符都被移除了),那么需要在栈中放入一个'0'字符。
  5. 结束处理:

    • 在栈顶放入一个字符串结束符\0
    • 返回栈的地址作为结果。

代码实现

char* removeKdigits(char* num, int k) {
    int length = strlen(num), top = -1, i = 0;
    char* stack = (char*)malloc(sizeof(char) * (length + 1));
    for (i; i < length; i++) {
        while (top != -1 && stack[top] > num[i] && k > 0) {
            top--;
            k--;
        }
        if (num[i] != '0' || top != -1)
            stack[++top] = num[i];
    }
    while (k > 0 && top > -1) {
        top--;
        k--;
    }
    if (top == -1)
        stack[++top] = '0';
    stack[++top] = '\0';
    return stack;
}

17. 电话号码的字母组合

题目描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

解题思路

  1. 初始化
    • 定义二维字符数组 map,将每个数字映射到其对应的字母集合。
    • 定义全局变量 path(用于存储当前组合),ans(用于存储所有组合),pathsize 和 anssize(分别用于跟踪 path 和 ans 的大小),以及 n(输入数字字符串的长度)。
  2. letterCombinations 函数
    • 获取输入数字字符串的长度 n
    • 为 path 和 ans 分配内存空间。
    • 检查如果 n 为0,则直接返回空数组,并设置 returnSize 为0。
  3. 回溯函数 backtrace
    • 递归终止条件:如果已处理完所有数字字符(idx == n),则复制当前 path 到新字符串 temp,并将 temp 添加到 ans 数组中。
    • 递归过程
      • 获取当前数字字符在 map 中对应的字母集合 words
      • 遍历 words 中的每个字母:
        • 将当前字母添加到 path 中。
        • 递归调用 backtrace 函数处理下一个数字字符。
        • 回溯:将 path 中的最后一个字母移除,以尝试 words 中的下一个字母。
  4. 返回结果
    • 在 letterCombinations 函数中,将 anssize 赋值给 returnSize
    • 返回 ans 数组,其中包含了所有可能的字母组合。

代码实现

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
char map[10][5] = {"",    "",    "abc",  "def", "ghi",
                   "jkl", "mno", "pqrs", "tuv", "wxyz"};
char* path;
char** ans;
int pathsize, anssize, n;
void backtrace(int idx, char* digits) {
    if (idx == n) {
        char* temp = (char*)malloc(sizeof(char) * (n + 1));
        for (int i = 0; i < n; i++)
            temp[i] = path[i];
        temp[n] = '\0';
        ans[anssize++] = temp;
        return;
    }
    char* words = map[digits[idx] - '0'];
    for (int i = 0; i < strlen(words); i++) {
        path[pathsize++] = words[i];
        backtrace(idx + 1, digits);
        pathsize--;
    }
}
char** letterCombinations(char* digits, int* returnSize) {
    n = strlen(digits);
    path = (char*)malloc(sizeof(char) * n);
    ans = (char**)malloc(sizeof(char*) * 300);
    anssize = pathsize = 0;
    if (n == 0) {
        *returnSize = 0;
        return ans;
    }
    backtrace(0, digits);
    *returnSize = anssize;
    return ans;
}

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值