1、数制转换,将十进制的数值转换成十六进制及以下的进制
#include <stdlib.h>
/**
思路:利用栈的先进后出特性
*/
void NumSwitch(int num, int targeNum){
if (targeNum>16) {
printf("⚠️该算法仅支持十六进制及以下的转换\n");
return;
}
int maxSize = 20;
//开辟动态数组
char *result = (char *)malloc(sizeof(char)*maxSize);
//栈顶
int top = -1;
while (num) {
if (top == 20 - 1) {//当数组空间满了再扩容
result = realloc(result, sizeof(char)*(maxSize += 10)); }
top++;
int r = num % targeNum;
switch (r) {
case 10:
result[top] = 'a';
break;
case 11:
result[top] = 'b';
break;
case 12:
result[top] = 'c';
break;
case 13:
result[top] = 'd';
break;
case 14:
result[top] = 'e';
break;
case 15:
result[top] = 'f';
break;
default:
result[top] = r + '0';
break;
}
num = num / targeNum;
}
printf("转换后的值为:");
while (top>-1) {
printf("%c",result[top]);
top--;
}
printf("\n");
}
2、括号匹配检测
假设表达式中允许包含两种括号:圆括号与⽅括号,其嵌套顺序随意,即([]()) 或者[([][])]都是正
确的.⽽这[(]或者(()])或者([()) 都是不正确的格式. 检验括号是否匹配的⽅法可⽤”期待的急迫程度"这个概念来描述.例如,考虑以下括号的判断: [ ( [ ] [ ] ) ]
/**
思路:
1、将字符串第一个字符入栈
2、从第二个字符开始遍历字符串,定义为e = data[i],每次循环取出栈顶元素
3、当栈顶元素为[、{ 、( 左括号时分别判断,以 [ 为例子:
①若果e != ]时,则e入栈,否则则出栈
②其余括号如 [
4、当栈顶元素不为这三种左括号时(也就是栈顶元素不存在)则直接入栈
5、当循环结束时,如果栈为空栈,则括号匹配成功,否则失败
*/
Status MatchStack(SqStack stack, char *data){
PushStack(&stack, data[0]);
int i = 1;
while (i<strlen(data)) {
//栈顶元素
char top = GetStackElemData(stack);
char e = data[i];
switch (top) {
case '[':
{
if (e != ']') {//入栈
PushStack(&stack, e);
}else{
PopStack(&stack);
}
}
break;
case '{':
{
if (e != '}') {//入栈
PushStack(&stack, e);
}else{
PopStack(&stack);
}
}
break;
case '(':
{
if (e != ')') {//入栈
PushStack(&stack, e);
}else{
PopStack(&stack);
}
}
break;
case '0':
{
PushStack(&stack, e);
}
break;
default:
break;
}
i++;
}
if (EmptyStack(stack)) {
printf("括号匹配正确\n");
return ERROR;
}else{
printf("括号匹配错误\n");
return OK;
}
}3、杨辉三角的实现
#include <stdio.h>
#include <stdlib.h>
/**
思路:使用二维数组处理 result[i][j]
1、杨辉三角的第一列都是1,即result[0][j] = 1;
2、当i == j时,result[i][j] = 1;
3、根据杨辉三角的性质我们发现 result[i][j] = result[i-1][j-1] + result[i-1][j];
*/
int **YangTrigonometry(int rowNum){
int **result = (int **)malloc(sizeof(int *)*rowNum);
for (int i = 0; i<rowNum; i++) {
//第i行开辟i+1个空间
result[i] = (int *)malloc(sizeof(int)*(i+1));
result[i][0] = 1;
result[i][i] = 1;
for (int j = 1; j<i; j++) {
result[i][j] = result[i-1][j-1] + result[i-1][j];
}
}
return result;
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
int **result = YangTrigonometry(6);
for (int i = 0; i<6; i++) {
for (int j = 0; j<i; j++) {
printf("%4d",result[i][j]);
}
printf("\n");
}
return 0;
}4、爬楼梯问题
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不
同的⽅法可以爬到楼顶呢?注意:给定 n 是⼀个正整数
/**
递归算法:
1、要计算n有多少个方法就要先计算n-1和n-2
2、当n<=2时结束递归, n == 1 return 1; n == 2 return 2;
*/
long long GetNum(int n){
if (n <= 2) {
if (n == 1) {
return 1;
}
return 2;
}else{
return GetNum(n-2) + GetNum(n - 1);
}
}
/**
动态规划算法
1、n == 1时,有1种,n == 2时,有2种
2、n == 3时,有 1 + 2 = 3种,即f(3) = f(1) + f(2)
3、n == 4时,有 2 + 3 = 5种,即f(4) = f(2) + f(3),因此可推算出f(n) = f(n - 1) + f(n - 2),其中n>2
*/
long long GetNum2(int n){
long long sum = 0;
if (n == 1) {
sum = 1;
}else if (n == 2){
sum = 2;
}else{
int *result = (int*)malloc(sizeof(int)*n);
result[0] = 1;
result[1] = 2;
for (int i = 2; i<n; i++) {
result[i] = result[i - 1] + result[i - 2];
}
sum = result[n-1];
free(result);
}
return sum;
}
5、气温问题
根据每⽇⽓温列表,请重新⽣成⼀个列表,对应位置的输⼊是你需要再等待多久温度才
会升⾼超过该⽇的天数。如果之后都不会升⾼,请在该位置0来代替。例如,给定⼀个列
表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1,
1, 0, 0]。提示:⽓温 列表⻓度的范围是 [1, 30000]。每个⽓温的值的均为华⽒度,都是
在 [30, 100] 范围内的整数
/**
思路:
1、第一层循环历气温数组,从i= 0开始,到length-1结束,因为最后一个气温不会出现比它高的
2、第二层循环 j 从 j = i + 1开始,直到 j = length 结束
4、如果list[j]>list[i],则找到了比list[i]高的气温,此时reslut[i] = j - i,跳出二层循环; 否则result[i] = 0;
*/
void RankTemperatures1(int *list, int length){
int *reslut = (int *)malloc(sizeof(int)*length);
reslut[length - 1] = 0;
for (int i = 0; i<length - 1; i++) {
if (i > 0 && list[i] == list[i - 1]) {
reslut[i] = reslut[i - 1] == 0 ? 0 : reslut[i - 1] - 1;
}else{
for (int j = i + 1; j<length; j++) {
if (list[i] < list[j]) {
reslut[i] = j - i;
break;
}else{
if (j == length - 1) {
reslut[i] = 0;
break;
}
//或者直接reslut[i] = 0;
}
}
}
}
printf("计算结果是:");
for (int i = 0; i<length; i++) {
printf("%2d",reslut[i]);
}
printf("\n");
}
/**
跳跃法
思路:
1、第一层循环从右到左遍历气温数组,最后一天气温不会升高,result[length] = 0;
2、第一层循环从倒数第二个数据开始遍历,即 i = length - 2,直到 i== 0结束
3、第二层循环 j 从 j = i + 1开始,直到 j = length - 1结束
4、如果list[j]>list[i],则找到了比list[i]高的气温,此时reslut[i] = j - i,跳出二层循环; 否则result[i] = 0;
*/
void RankTemperatures2(int *list, int length) {
int *reslut = (int *)malloc(sizeof(int)*length);
reslut[length - 1] = 0;
for (int i = length - 2; i>=0; i--) {
for (int j = i + 1; j<length; j++) {
if (list[i] < list[j]) {
reslut[i] = j - i;
break;
}else{
if (reslut[j] == 0) {//表明没有找到比list[i]高的气温
reslut[i] = 0 ;
break;
}
//或者
// reslut[i] = 0;
}
}
}
printf("计算结果是:");
for (int i = 0; i<length; i++) {
printf("%2d",reslut[i]);
}
printf("\n");
}
/**
当前算法逻辑参考,有具体讲解 https://leetcode-cn.com/problems/daily-temperatures/solution/leetcode-tu-jie-739mei-ri-wen-du-by-misterbooo/
思路: 栈中需要记录气温以及该气温在气温列表中的位置
1、开辟reslut数组记录相差天数
1、遍历气温数组,将reslut[i]先设置成0,记录当前气温为temp = list[i]
2、判断栈是否为空栈,如果不是空栈:
①、取出栈顶top,当栈顶top的气温小于temp时,计算当前 i 与栈顶top气温位置的差值,此差值即栈顶气温下一个超过它的天数
②、满足①,出栈
③、循环①②,直到栈为空
3、每个气温元素都要入栈
*/
void RankTemperatures3(int *list, int length){
SqStack stack;
InitStack(&stack);
//给结果先赋值为0
int *result = (int *)malloc(sizeof(int)*length);
//遍历数组
for (int i = 0; i<sizeof(list); i++) {
printf("当前值为:%d\n",i);
result[i] = 0;
int temp = list[i];
while (!EmpthStack(stack)) {//如果栈不为空,取出栈顶元素
ListSNode top = GetTopNodeStack(&stack);
if (!top) {
continue;
}
if (temp > top->data) {//如果当前数组元素比栈顶元素的值大,则表示找到了气温高的
//计算天数差别
result[top->index] = i - top->index;
//找到后出栈
PopStck(&stack);
}else{
break;
}
}
//将数组中气温入栈,栈中记录元素的位置i
PushStack(&stack, temp, i);
}
printf("结果是:");
for (int i = 0; i<sizeof(&result); i++) {
printf("%2d",result[i]);
}
printf("\n");
}
6、字符串编码问题
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
例如:
s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
/**
方法一
思路:
1、遍历字符串list,获得复制的次数count
2、使用result保存出栈之前保存的字符串
3、遇到 ‘[’则入栈
4、遇到 ‘]’ 则出栈,出栈时要复制字符串,并将复制后的字符串拼接到原来result后面
5、若字符不是 ‘[’ 也不是 ']' ,则直接拼接到result后面
*/
Status DecodeString(ModelStack *stack, char *list){
SElemType result = (SElemType)malloc(sizeof(char)*(MAXSIZE));
*result = '\0';
int count = 0;
for (int i = 0; i<strlen(list); i++) {
char data = list[i];
if (data >= '0' && data <= '9') {
count = 10 * count + data - '0';
}else if (data == '['){//入栈
ModelNode node = (ModelNode)malloc(sizeof(StrackNode));
node->next = NULL;
//将解码后(也可能是空)的字符串入栈保存起来
node->data = result;
node->count = count;
PushStack(stack, node);
//重置count、result
count = 0;
//每次入栈后需要给result重新开辟空间,否则下次入栈的信息会把上次的覆盖掉
result = (SElemType)malloc(sizeof(char)*(MAXSIZE));
*result = '\0';
}else if (data == ']'){//出栈
ModelNode node = PopStack(stack);
if (node) {
//这是当前最深的或[]里的字符串,比如3[a]2[bc]里面的bc或者3[a2[c]]中c
SElemType cur = result;
//取出栈中保存的解码后字符串(这个字符串需要放在前面的)
result = (node->data);
SElemType temp = (SElemType)malloc(sizeof(char)*MAXSIZE);
*temp = '\0';
if (node->count>0) {
for (int i = 0; i<node->count; i++) {//获得字符串拼接
strcat(temp, cur);
}
}else{
strcat(temp, cur);
}
//将出栈后拼接完成的字符串拼接到result上
strcat(result, temp);
//释放结点node
free(node);
}
}else{
//将[]里面的字符串拼接成一个字符串result,比如3[a]2[bc]中的bc拼接成result
strncat(result, &data, 1);
}
}
printf("结果的值为:");
for (int i = 0; i<strlen(result); i++) {
printf("%c",result[i]);
}
printf("\n");
return OK;
}
/**
方法二
思路:以字符串list = "13[abc]"为例
1、遍历字符串list中的字符,当没有遇到 ']' 时,字符均入栈stack
2、当遇到字符 ‘[’ 时取出stack栈中的字符串
①当遇到字符 ‘[’ 时先停止出栈,stack栈中元素从栈顶到栈底依次为c、b、a、[、3、1
②将c、b、a存储到新的栈中temp,temp栈中元素从栈顶到栈底依次为a、b、c
③取出stack栈中需要复制字符串的个数n,比如n=13,此时stack栈已经为空了
④将temp栈中的元素取出并复制n遍后入栈stack
⑤释放临时栈temp存储空间
3、stack中追加结束字符 ‘\0’,此时stack栈中的内容就是编码后的字符串
*/
char *GetDecodeString(char *list){
if (!list) {
return list;
}
int stackSize = 20;
char *stack = (char *)malloc(sizeof(char)*stackSize);
int top = -1;
//字符串长度
int length = (int)strlen(list);
for (int i = 0; i<length; i++) {
char s = list[i];
if (s != ']') {//入栈
if (top == stackSize - 1) {//存储空间不够,扩容
stack = realloc(stack, sizeof(char)*(stackSize += stackSize));
}
stack[++top] = s;
}else{//出栈
/* 取[]之间的字符串,并保存到临时栈temp中*/
int tempSize = 10;
char *temp = (char *)malloc(sizeof(char)*tempSize);
int tempTop = -1;
while (stack[top] != '[') {//只取【之前的字符,不要数字
if (tempTop == tempSize - 1) {//临时栈temp存储空间不够,则扩容
temp = realloc(temp, sizeof(char)*(tempSize += tempSize));
}
temp[++tempTop] = stack[top];
top--;
}
/* 取[之前的数字 */
char num[11];
//记录数字的上限
int stopNumTop = top;
//此时top指向是'[',所以top--
top--;
//找到数字的下限
while (top != -1 && stack[top] >= '0' && stack[top] <= '9') {
top--;
}
//此时top多减了1
for (int j = top + 1; j<stopNumTop; j++) {
num[j - (top + 1)] = stack[j];
}
//给数字添加结束符
num[stopNumTop - (top + 1)] = '\0';
//将字符串数据转成int
int copyNum = atoi(num);
if (copyNum>0) {
for (int k = 0; k < copyNum; k++) {
int topTemp = tempTop;
while (topTemp != -1) {
stack[++top] = temp[topTemp];
topTemp--;
}
}
}else{
if (tempTop > -1) {
int topTemp = tempTop;
while (topTemp != -1) {
stack[++top] = temp[topTemp];
topTemp--;
}
}
}
//释放temp栈内存
free(temp);
temp = NULL;
}
}
//调整动态内存空间,减少浪费
char *reslut = realloc(stack, sizeof(char)*(top+1));
top++;
reslut[top] = '\0';
return reslut;
}
7、字符串去重并且字典序最小问题
给你⼀个仅包含⼩写字⺟的字符串,请你去除字符串中重复的字⺟,使得每个字⺟只出现⼀
次。需保证返回结果的字典序最⼩(要求不能打乱其他字符的相对位置)
例如:''cbacdcbc’',返回''acdb'';
例如:"bcabc",返回"abc"
/**
思路
1、给字符串list中所有的字符添加出现次数
2、每次遍历字符时判断是否已经出现了,如果已经出现则给出现的次数减一
3、如果没有出现过
①判断栈是否不为空,如果不为空,且栈顶元素大于list[i]字符,且该栈顶元素出现的次数大于1,则表示后面还有栈顶元素出现,那么久出栈,并且栈顶元素出现的次数减一
②如果①没有满足,则入栈
4、给栈顶添加结束符
5、栈中元素即去重后的字典序最小的字符串
*/
char *GetMinString(char *list){
if (strlen(list) == 0) {
return "";
}else if (strlen(list) == 1){
return list;
}
int length = (int)strlen(list);
char *resultStack = (char*)malloc(sizeof(char)*(length + 2));
//showCount用来记录每个字符出现的次数
int showCount[26] = {0};
for (int i = 0; i<length; i++) {
//list[i] - 'a'可以计算出唯一的位置值,可以称为n,当这个n同的时候表示出现了,所以要++
showCount[list[i] - 'a']++;
}
//栈顶位置
int top = -1;
char temp;
for (int i = 0; i<length; i++) {
temp = list[i];
bool isExist = false;
for (int j = 0; j<length; j++) {
if (temp == resultStack[j]) {//当栈中出现了该元素
isExist = true;
break;
}
}
if (isExist) {//如果出现过,记录出现的次数要减一
showCount[temp - 'a']--;
}else{
while (top>-1 && //栈非空
resultStack[top]>temp && //栈顶的元素大于temp
showCount[resultStack[top] - 'a']>1) { //数组list后面还有栈顶元素
//栈顶元素出栈
top--;
//跳过该元素,记录栈顶元素出现的次数减一
showCount[resultStack[top] - 'a']--;
}
//栈顶++,入栈
top++;
resultStack[top] = temp;
}
}
//栈顶位置添加结束符
resultStack[++top] = '\0';
return resultStack;
}