括号匹配检验
假设表达式中允许包含三种括号:圆括号( )、方括号[ ]和花括号{ },其嵌套的顺序随意。 { ( [ ] ( ) ) }或[ { ( [ ] [ ] ) } ]等为正确的格式,[ ( ] 、( [ ( ) ) 、( ( ) ]均为不正确的格式。检验括号是否匹配的方法可用“期待的急迫程度”这个概念来描述。
思路:
{ [ ( ) ] } 题目要求检验一串括号表达式是否是正确的,利用栈的特性
- 遍历第一个字符{, 是起始符号 ,{入栈 ,栈顶 { ,当务之急,下一个得是}
- 遍历第二个字符[, 又是起始符号,[入栈,栈顶 [ ,[的急迫程度更高,下一个得是]
- 遍历第三个字符(, 又是起始符号,(入栈,栈顶 ( ,(的急迫程度更高,下一个得是)
- 遍历第四个字符), Wow,是终止符号,先去看看栈顶最急迫的是不是(,如果不是,这个表达式就不对[)?{)? 如果是(,继续往下走
- 遍历第五个字符], 终止符, 去看看栈顶是不是最急迫的[, 是,继续往下走
- 遍历第六个字符}, 终止符,去看看栈顶是不是最急迫的{,是,继续往下走,
- 直到遍历完毕,查看栈里是否还有元素,有,说明没有匹配玩,表达式不对
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OK 1
typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
/* 链栈的每一个节点,和单链表很像有没有 */
typedef struct StackNode {
ElemType data;
struct StackNode *next;
}StackNode;
typedef struct StackNode * StackNodePtr;
/* 栈结构 */
typedef struct
{
StackNodePtr top;
int count;
}LinkStack;
#pragma mark - 栈的基本操作
Status InitStack(LinkStack *S)
{
S->top = NULL;
S->count = 0;
return OK;
}
Status ClearStack(LinkStack *S)
{
if (S->top == NULL) return ERROR;
StackNodePtr p;
while (S->count != 0) {
p = S->top;
S->top = S->top->next;
free(p);
S->count--;
}
return OK;
}
int StackLength(LinkStack S)
{
return S.count;
}
Status StackEmpty(LinkStack S)
{
if (S.top == NULL) {
return OK;
} else {
return ERROR;
}
}
Status GetTop(LinkStack S, ElemType *e)
{
if (S.top == NULL) return ERROR;
// if (S->count == 0) return ERROR; // 也可以
*e = S.top->data;
return OK;
}
Status PushStack(LinkStack *S, ElemType e)
{
// 创建新元素
StackNodePtr p = (StackNodePtr)malloc(sizeof(StackNode));
if (p == NULL) return ERROR;
p->data = e;
p->next = S->top;
S->top = p;
S->count++;
return OK;
}
Status PopStack(LinkStack *S, ElemType *e)
{
if (S->top == NULL) return ERROR;
// if (S->count == 0) return ERROR; // 也可以
/* 将栈顶指针指向新的栈顶 */
StackNodePtr temp = S->top;
S->top = S->top->next;
if (e != NULL) {
*e = temp->data;
}
free(temp);
S->count--;
return OK;
}
Status DestoryStack(LinkStack *S)
{
ClearStack(S);
return OK;
}
#pragma mark - 核心方法
Status BracketsCheck(char *brackets)
{
// 创建栈
LinkStack S;
InitStack(&S);
/* flag可以不加,主要是为了能够在while外销毁栈 */
BOOL flag = NO;
char *c = brackets;
while (*c) {
switch (*c) {
case '{':
case '[':
case '(':
{
// push
PushStack(&S, *c);
}
break;
case ')':
{
if (StackEmpty(S)) {
flag = YES;
break;
}
ElemType popChar ;
PopStack(&S, &popChar);
if (popChar != '(') flag = YES;
}
break;
case ']':
{
if (StackEmpty(S)) {
flag = YES;
break;
}
ElemType popChar ;
PopStack(&S, &popChar);
if (popChar != '[') flag = YES;
}
break;
case '}':
{
if (StackEmpty(S)) {
flag = YES;
break;
}
ElemType popChar ;
PopStack(&S, &popChar);
if (popChar != '[') flag = YES;
}
break;
default:
break;
}
if (flag) {
break;
}
c++;
}
if (flag) {
// 销毁栈
DestoryStack(&S);
return ERROR;
}
// 最后,如果栈为空,则全部匹配完毕
if (StackEmpty(S)) {
// 销毁栈
DestoryStack(&S);
return OK;
} else {
// 销毁栈
DestoryStack(&S);
return ERROR;
}
}
int main(int argc, const char * argv[]) {
char str[30];
while (1) {
printf("请输入要检查的括号字符串:");
gets(str);
if (*str == '0') {
break;
}
if (BracketsCheck(str))
{
printf("括号匹配正确\n\n");
}
else
{
printf("括号匹配错误\n\n");
}
}
return 0;
}
每日气温
根据每日 气温 列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
思路
用单调递减栈
这道题最重要的题意,简单的说,temperatures = [73, 74, 75, 71, 69, 72, 76, 73] 遍历每个气温向右找第一个比自己大的气温,需要找几次才能找到。比如73,右边第一个比他大的是74,只要找一次,所以输出是1;75,右边找4次,才找到比他大的76,所以输出是4;71,向右找2次才找到比他大的72,所以输出是2.......依次,我们输出[1, 1, 4, 2, 1, 1, 0, 0]
默认result[8] = {0}
- (0,73)入栈,74>73,73出栈,(1,74)入栈,栈顶74。输出:result[0] = 1-0=1;
- 找比栈顶74大的元素,75>74,74出栈,(2,75)入栈。输出:result[1] = 2-1=1
- 找比栈顶75大的元素,71<75,(3,71)入栈
- 找比栈顶71大的元素, 69<71, (4,69)入栈
- 找比栈顶69大的元素,72>69, 找到比69大的,69出栈。输出:result[4] = 5-4=1
- 用(5,72) 和栈顶元素71比较,72是第一个比71大的元素,(3,71)出栈。result[3] = 5-3=2
- 栈顶75,72<75, (5,72)入栈
- 栈顶72与76比较,(5,72)出栈,栈顶75,result[5] = 6-5=1
- 栈顶75与76比较,(2,75)出栈, result[2] = 6-2=4
- 栈为空,(6,76)入栈
- 栈顶76与73比较,76和73后面均没有比自己大的
上面是单调递减栈,比栈顶元素大的,栈顶出栈,继续与新栈顶比较。比新栈顶小的,自己入栈,遍历下一个元素。栈顶始终比栈底小。
先定义一个栈及基本操作,因为列表长度最大到30000,所以我采用了链栈。
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OK 1
typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
//typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
typedef struct ElemType {
int place; // 输入数组中的位置
int value; // 输入数组中的元素
} ElemType;
/* 链栈的每一个节点,和单链表很像有没有 */
typedef struct StackNode {
ElemType data;
struct StackNode *next;
}StackNode;
typedef struct StackNode * StackNodePtr;
/* 栈结构 */
typedef struct
{
StackNodePtr top;
int count;
}LinkStack;
#pragma mark - 栈的基本操作
Status InitStack(LinkStack *S)
{
S->top = NULL;
S->count = 0;
return OK;
}
Status ClearStack(LinkStack *S)
{
if (S->top == NULL) return ERROR;
StackNodePtr p;
while (S->count != 0) {
p = S->top;
S->top = S->top->next;
free(p);
S->count--;
}
return OK;
}
int StackLength(LinkStack S)
{
return S.count;
}
Status StackEmpty(LinkStack S)
{
if (S.top == NULL) {
return OK;
} else {
return ERROR;
}
}
Status GetTop(LinkStack S, ElemType *e)
{
if (S.top == NULL) return ERROR;
// if (S->count == 0) return ERROR; // 也可以
*e = S.top->data;
return OK;
}
Status PushStack(LinkStack *S, ElemType e)
{
// 创建新元素
StackNodePtr p = (StackNodePtr)malloc(sizeof(StackNode));
if (p == NULL) return ERROR;
p->data = e;
p->next = S->top;
S->top = p;
S->count++;
return OK;
}
Status PopStack(LinkStack *S, ElemType *e)
{
if (S->top == NULL) return ERROR;
// if (S->count == 0) return ERROR; // 也可以
/* 将栈顶指针指向新的栈顶 */
StackNodePtr temp = S->top;
S->top = S->top->next;
if (e != NULL) {
*e = temp->data;
}
free(temp);
S->count--;
return OK;
}
Status DestoryStack(LinkStack *S)
{
ClearStack(S);
return OK;
}
核心代码
/// 每日温度
/// @param T 输入原始温度数组
/// @param returnArr 结果
Status DailyTempreatures(int *T, int TSize, int *returnArr)
{
// 创建栈
LinkStack S;
InitStack(&S);
int i = 0;
ElemType temp;
while (i != TSize) {
if (StackEmpty(S))
{
ElemType e ;
e.place = i;
e.value = T[i];
PushStack(&S, e);
}
else
{
GetTop(S, &temp);
if (T[i] < temp.value)
{
ElemType e ;
e.place = i;
e.value = T[i];
PushStack(&S, e);
}
else
{
PopStack(&S, &temp);
returnArr[temp.place] = i - temp.place;
continue;
}
}
i++;
}
return OK;
}
爬楼梯
题目:假设你正在爬楼梯。需要n阶你才能到达楼顶。每次你可以爬1到2个台阶。你有多少种不同的方法可以爬到楼顶呢?
思路:斐波那契数列
不是递归,每次保存前一次的计算结果,累加
/*
爬楼梯
n 是台阶数
*/
void ClimbStairs(int n)
{
int *arr = (int *)malloc(sizeof(int)*n);
if (arr == NULL) return;
for (int i = 0; i < n; i++) {
if (i == 0 || i == 1)
*(arr+i) = i+1;
else
*(arr+i) = *(arr+i-1) + *(arr+i-2);
}
printf("最大次数为:%d\n",*(arr+n-1));
free(arr);
}