目录
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
个数字,使得剩下的数字组成的数最小。
-
初始化:
- 获取输入字符串
num
的长度length
。 - 初始化一个栈
stack
,用于存放结果。栈的大小为length + 1
,因为最后还需要存放一个字符串结束符\0
。 - 初始化栈顶指针
top
为-1,表示栈为空。 - 初始化遍历索引
i
为0。
- 获取输入字符串
-
遍历输入字符串:
- 对于输入字符串中的每个字符,进行以下操作:
- 如果栈不为空且栈顶元素大于当前字符,并且还有剩余要移除的字符数
k
,那么将栈顶元素弹出,同时k
减1。这一步是为了确保栈内的元素是单调递增的,这样可以确保得到的数最小。 - 如果当前字符不是'0'或者栈不为空,那么将当前字符压入栈中。这里有一个条件判断是为了避免在结果的最前面出现前导零。
- 如果栈不为空且栈顶元素大于当前字符,并且还有剩余要移除的字符数
- 对于输入字符串中的每个字符,进行以下操作:
-
处理剩余的移除次数:
- 如果遍历完输入字符串后还有剩余的移除次数
k
,那么继续从栈顶弹出元素,直到移除次数用完或者栈为空。
- 如果遍历完输入字符串后还有剩余的移除次数
-
处理特殊情况:
- 如果栈为空(即所有字符都被移除了),那么需要在栈中放入一个'0'字符。
-
结束处理:
- 在栈顶放入一个字符串结束符
\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']
的一个数字。
解题思路
- 初始化:
- 定义二维字符数组
map
,将每个数字映射到其对应的字母集合。 - 定义全局变量
path
(用于存储当前组合),ans
(用于存储所有组合),pathsize
和anssize
(分别用于跟踪path
和ans
的大小),以及n
(输入数字字符串的长度)。
- 定义二维字符数组
- letterCombinations 函数:
- 获取输入数字字符串的长度
n
。 - 为
path
和ans
分配内存空间。 - 检查如果
n
为0,则直接返回空数组,并设置returnSize
为0。
- 获取输入数字字符串的长度
- 回溯函数 backtrace:
- 递归终止条件:如果已处理完所有数字字符(
idx == n
),则复制当前path
到新字符串temp
,并将temp
添加到ans
数组中。 - 递归过程:
- 获取当前数字字符在
map
中对应的字母集合words
。 - 遍历
words
中的每个字母:- 将当前字母添加到
path
中。 - 递归调用
backtrace
函数处理下一个数字字符。 - 回溯:将
path
中的最后一个字母移除,以尝试words
中的下一个字母。
- 将当前字母添加到
- 获取当前数字字符在
- 递归终止条件:如果已处理完所有数字字符(
- 返回结果:
- 在
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;
}