LeetCode----Stack----C语言

155. Min Stack—Easy

题目

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
push(x) – Push element x onto stack.
pop() – Removes the element on top of the stack.
top() – Get the top element.
getMin() – Retrieve the minimum element in the stack.

思路

简单栈的实现
解法一有瑕疵,static定义的 Minstack,只能实例化一个元素;
应该用解法二 malloc 分配空间。

AC代码
在这里插入图片描述
解法一:(有瑕疵)

typedef struct {
    int max_size;
    int top;
    int min_elem;
    int *val;
} MinStack;

/** initialize your data structure here. */
MinStack* minStackCreate(int maxSize) {
    if (maxSize <= 0)
        exit(-1);
    static MinStack obj;
    obj.val = (int* )malloc(maxSize*sizeof(int));
    if (obj.val == NULL)
        exit(-1);
    obj.max_size = maxSize;
    obj.top = -1;
    
    return &obj;
}

void minStackPush(MinStack* obj, int x) {
    if (obj->top < obj->max_size){
        obj->val[++obj->top] = x;
        if (obj->top == 0 || obj->min_elem > x)
            obj->min_elem = x;
    }
    else
        exit(-1);
}

void minStackPop(MinStack* obj) {
    if (obj->top >= 0){
        if (obj->min_elem == obj->val[obj->top]){
            obj->min_elem = obj->val[0];
            for (int i=1; i<obj->top; i++)
                if (obj->min_elem > obj->val[i])
                    obj->min_elem = obj->val[i];
        }
        obj->top--;
    }
    else
        exit(-1);
}

int minStackTop(MinStack* obj) {
    if (obj->top >= 0)
        return obj->val[obj->top];
    else
        exit(-1);
}

int minStackGetMin(MinStack* obj) {
    return obj->min_elem;
}

void minStackFree(MinStack* obj) {
    if (obj->val != NULL)
        free(obj->val);
}

/**
 * Your MinStack struct will be instantiated and called as such:
 * struct MinStack* obj = minStackCreate(maxSize);
 * minStackPush(obj, x);
 * minStackPop(obj);
 * int param_3 = minStackTop(obj);
 * int param_4 = minStackGetMin(obj);
 * minStackFree(obj);
 */

解法二:(只贴出差异化代码)


/** initialize your data structure here. */
MinStack* minStackCreate(int maxSize) {
    if (maxSize <= 0)
        exit(-1);
    MinStack* obj;
    obj = malloc(sizeof(MinStack));
    obj->val = (int* )malloc(maxSize*sizeof(int));
    if (obj->val == NULL)
        exit(-1);
    obj->max_size = maxSize;
    obj->top = -1;
    
    return obj;
}


232. Implement Queue using Stacks—Easy

题目

Implement the following operations of a queue using stacks.
push(x) – Push element x to the back of queue.
pop() – Removes the element from in front of queue.
peek() – Get the front element.
empty() – Return whether the queue is empty.

思路

经典双栈模拟队列问题!
入队操作:都在栈1执行,如果栈1非满,则入栈;如果栈1满,栈2空,则将栈1挪入栈2,将元素压入栈1。
出队操作:都在栈2执行,如果栈2空,栈1非空,则将栈1元素挪入栈2,然后从栈2出栈;如果栈2非空,则直接出栈即可。
挪入操作:栈1出栈一个元素,压入栈2,直到栈1为空。

AC代码
在这里插入图片描述

typedef struct {
    int max_size;
    int top;
    int* val;
} MyStack;

/**Initialize your data structure here. */
MyStack* myStackCreate(int maxSize) {
    MyStack* obj;
    obj = malloc(sizeof(MyStack));
    if (maxSize <= 0) exit(-1);
    obj->val = (int* )malloc(maxSize*sizeof(int));
    if (obj->val == NULL) exit(-1);
    obj->max_size = maxSize;
    obj->top = -1;
    
    return obj;
}

/** Push element x to the top of stack.*/
void myStackPush(MyStack* obj, int x) {
    if (obj->top < obj->max_size) 
        obj->val[++obj->top] = x;
}

/** Remove element x to the top of stack. */
void myStackPop(MyStack* obj) {
    if (obj->top >= 0)
        obj->top--;
}

/** return element x to the top of stack. */
int myStackTop(MyStack* obj) {
    return obj->val[obj->top];
}

/** Judge if stack is empty. */
bool myStackEmpty(MyStack* obj) {
    if (obj->top == -1) return true;
    else return false;
}

/** return stack top. */
int myStackNum(MyStack* obj) {
    return obj->top;
}

void myStackFree(MyStack* obj) {
    if (obj->val != NULL)
        free(obj->val);
    obj->val = NULL;
}

typedef struct {
    int max_size;
    int num;
    MyStack* s1;
    MyStack* s2;
} MyQueue;

/** Initialize your data structure here. */
MyQueue* myQueueCreate(int maxSize) {
    MyQueue* obj;
    obj = malloc(sizeof(MyQueue));
    obj->max_size = maxSize;
    obj->num = 0;
    obj->s1 = myStackCreate((maxSize+1)/2);
    obj->s2 = myStackCreate(maxSize/2);
    
    return obj;
}

/** Push element x to the back of queue. */
void myQueuePush(MyQueue* obj, int x) {
    if (myStackNum(obj->s1) < (obj->max_size+1)/2){ 
        myStackPush(obj->s1,x);
        obj->num++;
    }
    else if (myStackEmpty(obj->s2)) {
        for (int i=0; i<myStackNum(obj->s1); i++) {
            int tmp = myStackTop(obj->s1);
            myStackPop(obj->s1);
            myStackPush(obj->s2,tmp);
        }
        myStackPush(obj->s1,x);
        obj->num++;
    }
}

/** Removes the element from in front of queue and returns that element. */
int myQueuePop(MyQueue* obj) {
    if (!myStackEmpty(obj->s2)) {
        int tmp = myStackTop(obj->s2);
        myStackPop(obj->s2);
        obj->num--;
        return tmp;
    }
    else if (!myStackEmpty(obj->s1)){
        int num = myStackNum(obj->s1);
        for (int i=0; i<=num; i++) {
            int tmp = myStackTop(obj->s1);
            myStackPop(obj->s1);
            myStackPush(obj->s2,tmp);
        }
        int tmp = myStackTop(obj->s2);
        myStackPop(obj->s2);
        obj->num--;
        return tmp;
    }
    
    return 0;
}

/** Get the front element. */
int myQueuePeek(MyQueue* obj) {
     if (!myStackEmpty(obj->s2)) 
        return  myStackTop(obj->s2);
    else if (!myStackEmpty(obj->s1)){
        int num = myStackNum(obj->s1);
        for (int i=0; i<=num; i++) {
            int tmp = myStackTop(obj->s1);
            myStackPop(obj->s1);
            myStackPush(obj->s2,tmp);
        }
         return  myStackTop(obj->s2);
    }
    
    return 0;
}

/** Returns whether the queue is empty. */
bool myQueueEmpty(MyQueue* obj) {
    if (obj->num == 0) return true;
    else return false;
}

void myQueueFree(MyQueue* obj) {
    myStackFree(obj->s1);
    myStackFree(obj->s2);
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * struct MyQueue* obj = myQueueCreate(maxSize);
 * myQueuePush(obj, x);
 * int param_2 = myQueuePop(obj);
 * int param_3 = myQueuePeek(obj);
 * bool param_4 = myQueueEmpty(obj);
 * myQueueFree(obj);
 */

150. Evaluate Reverse Polish Notation—Medium

题目

Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are +, -, *, /. Each operand may be an integer or another expression.
Note:
Division between two integers should truncate toward zero.
The given RPN expression is always valid. That means the expression would always evaluate to a result and there won’t be any divide by zero operation.

思路

每次遇到符号时,出栈两个数,做运算,然后将结果压栈;每次遇到数字,将数字压栈。
注意区分负号和减号,注意两个操作数顺序。

AC代码
在这里插入图片描述

int top = -1;
int max_size = 64000;
int stack[64000];

void push(int x) {
    if (top < max_size)
        stack[++top] = x;
}

void pop() {
    if (top >= 0)
        top--;
}

int mytop() {
    if (top >= 0)
        return stack[top];
    return -1;
}

int evalRPN(char** tokens, int tokensSize) {
    for (int i=0; i<tokensSize; i++) {
        switch ((*tokens)[0]) {
        case '+':
        case '-':
        case '*':
        case '/':{
                    if ((*tokens)[1] == '\0'){
                        int src2 = mytop();
                        pop();
                        int src1 = mytop();
                        pop();
                        int dest;
                        switch ((*tokens)[0]) {
                        case '+':dest = src1 + src2; break;
                        case '-':dest = src1 - src2; break;
                        case '*':dest = src1 * src2; break;
                        case '/':dest = src1 / src2; break;             
                        }
                        push(dest);
                        break;
                    }
                 }
        default: {
                    int dest=0,i=0,sign=1;
                    if ((*tokens)[i] == '-') {
                        i++;
                        sign=-1;
                    }
                    while ((*tokens)[i] != '\0')
                        dest = dest*10 + (*tokens)[i++]-'0';
                    push(dest*sign);
                 }
        }
        tokens++;
    }
    
    return mytop();
}

71 Simplify Path—Medium(出错10次)

题目

Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.
In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period … moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix
Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path.

思路

一次遍历,状态机思路;
注意:本题出错次数较多,可能晚上身体不舒服,但同时也是对unix系统文件名的不熟悉,比如 .aa …a 这样的文件,理解稍有问题。

AC代码
在这里插入图片描述

char stack[64000][100];
int top = -1;

void push(char* path) {
    if (top < 64000)
        strcpy(stack[++top],path);
}

void pop () {
    if (top >= 0) 
        top--;
}

char* simplifyPath(char* path) {
    int len = strlen(path);
    enum INPUT {begin_slashes,end_slashes,begin_path,end_path};
    enum INPUT status = begin_slashes;
    static char tmp[64000];
    int tmp_iter;
    top = -1;
    
    for (int i=0; i<len; i++) {
        switch (status) {
            case begin_slashes: {
                                    if (path[i] == '/') {
                                        tmp_iter = 0;
                                        tmp[tmp_iter++] = '/';
                                        status = end_slashes;
                                    }                                                               
                                    break;
                                }
            case end_slashes:   {
                                    if (path[i] == '/') 
                                        break;
                                    status = begin_path;
                                } 
            case begin_path:    {
                                    if (path[i] == '.') {
                                        if (i<len-1 && path[i+1]!='/') {
                                            if (path[i+1] == '.') {
                                                if (i<len-2 && path[i+2]!='/') 
                                                    status = end_path; 
                                                else {
                                                    i++;
                                                    pop();
                                                    status = begin_slashes;
                                                    break;
                                                }
                                            } 
                                            else
                                                status = end_path; 
                                        }
                                        else{ 
                                            status = begin_slashes;  
                                            break;
                                        }  
                                    }
                                    else 
                                        status = end_path; 
                                }
            case end_path:      {
                                    if (path[i] == '/') {
                                        tmp[tmp_iter++] = 0;
                                        push(tmp);
                                        i--;
                                        status = begin_slashes;
                                    }
                                    else{
                                        tmp[tmp_iter++] = path[i];
                                        if (i == len-1) {
                                            tmp[tmp_iter++] = 0;
                                            push(tmp);
                                        }
                                    }
                                    break;
                                }
        }   
    }
    tmp_iter = 0;
    if (top == -1)
        strcpy(tmp,"/");
    else{
        for (int i=0; i<=top; i++) {
            int len = strlen(stack[i]);
            strcpy(&tmp[tmp_iter], stack[i]);
            tmp_iter += len;
        }
    }
    
    return tmp;
}

388. Longest Absolute File Path—Medium(出错4次)

题目
题目描述

思路

文件或目录以 ‘\n’ 或 ‘\0’ 结尾,’\t’ 表示目录或文件的等级。
利用栈,记录最长的文件路径,返回即可

AC代码
在这里插入图片描述

#define MAX_PATH 1000
#define MAX_STACK 64000

typedef struct {
    int top;
    int maxPath;
    int numPath;
    int len[MAX_PATH];
}Stack;

void push(Stack* s, char* elem, int sign) {
    int len = strlen(elem);
    if (s->top <= MAX_STACK) {
        s->len[++s->top] = len;
        s->numPath += len;
        if (sign==1 && s->numPath > s->maxPath)
            s->maxPath = s->numPath;
    }
}

void pop(Stack* s) {
    if (s->top >= 0)
        s->numPath -= s->len[s->top--];
}

int lengthLongestPath(char* input) {
    Stack s = {
        .top = -1,
        .maxPath = 0,
        .numPath = 0
    };
    char tmp[MAX_PATH];
    int len = strlen(input);
    int flag = 0;
    int space_count = 0;
    int leval = 0;
    int status = 0;
    int tmp_iter = 0;
    int currLeval;
 
    for (int i=0; i<len+1; i++) {
        switch (status) {
            case 0: {
                        if (input[i] != '\n' && input[i] != '\0') {
                            tmp[tmp_iter++] = input[i];
                            if (input[i] == '.')
                                flag = 1;
                        }
                        else{
                            tmp[tmp_iter] = 0;
                            push(&s, tmp, flag); 
                            leval++;
                            currLeval = 0;
                            status = 1;
                        }
                        break;
                    }
            case 1: {
                        if (input[i] == '\t')
                            currLeval++;
                        else {
                            while (leval > currLeval) {
                                pop(&s);
                                leval--;
                            }       
                            tmp_iter = 1;
                            if (leval != 0)
                                tmp[tmp_iter++]='/';
                            flag = 0;
                            status = 0;
                        }
                    }
        }
    }
    
    return s.maxPath;
}

REF:(这个实现比较简洁)

#define MAX_N 10005

int dlen[MAX_N];

int lengthLongestPath(char* input) {
    int pos = 0;
    int level = 0;
    int res = 0;
    
    while(input[pos]) {
        int next = pos;
        int flag = 0;
        while(input[next] != '\n' && input[next] != '\0') {
            ++next;
            if(input[next] == '.')
                flag = 1;
        }
        int clen = next - pos;
        if(flag == 1) {
            int plen = clen;
            for(int i = 0; i < level; ++i)
                plen += dlen[i];
            if(res < plen)
                res = plen;
        }
        else{
            dlen[level] = clen + 1;
        }
        int tlevel = 0;
        if(input[next])
            ++next;
        while(input[next] == '\t') {
            ++tlevel;
            ++next;
        }
        level = tlevel;
        pos = next;
    }
    
    return res;
}

394. Decode String—Medium

题目

Given an encoded string, return it’s decoded string.
The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.
You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.
Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won’t be input like 3a or 2[4].

思路

需要一个栈来存储数据,实现思路并不困难,注意细节。

AC代码
在这里插入图片描述

#define MAX_STACK 64000

char stack[MAX_STACK];
char tmp[MAX_STACK];

char* decodeString(char* s) {
    int len = strlen(s);
    int top = -1;
    
    memset(stack,0,sizeof(stack));
    for (int i=0; i<len; i++) {
        if (s[i] != ']') {
            stack[++top] = s[i];
            continue;
        }
        int pos = top;
        for (; pos>=0&&stack[pos]!='['; pos--);
        int rec_pos = pos;
        for (--pos; pos>=0; pos--)
            if (stack[pos]<'0' || stack[pos]>'9') break;
        pos++;
        int num=0;
        for (int j=pos; j<rec_pos; j++)
            num = num*10+stack[j]-'0';
        int len = top-rec_pos;
        int begin_cp = pos-len;
        strncpy(tmp,&stack[rec_pos+1],len);
        for (int j=0; j<num; j++) {
            begin_cp += len;
            strncpy(&stack[begin_cp],tmp,len);
        }
        top = pos+num*len-1; 
    }
    stack[++top] = 0;
    
    return stack;
}

224. Basic Calculator—Hard

题目

Implement a basic calculator to evaluate a simple expression string.
The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .

思路

我将此题作为标准的表达式求值(±*/)做了。
解法一:
step 1:提取token
step 2:中缀表达式转后缀表达式
step 3:计算
解法二:
step 1:提取token
step 2:利用语法树递归求解
cmp:解法一时间远优于解法二,再次证明递归效率的底下;但是显然解法二形式更简单,容易写。
解法三:
针对本体题具体解法

AC代码
解法一:
在这里插入图片描述

#define MAX 1000000

typedef struct {
    int top;
    int num[MAX];
}StackInt;

void pushInt(StackInt* s,int elem) {
    if(s->top < MAX) {
        s->num[++s->top] = elem;
    }
}

void popInt(StackInt* s) {
    if(s->top >= 0) {
        s->top--;
    }
}

int topInt(StackInt* s) {
    if(s->top >= 0) {
        return s->num[s->top];
    }
    
    return 0;
}

typedef struct {
    int top;
    char operator[MAX];
}StackChar;

void pushChar(StackChar* s,char elem) {
    if(s->top < MAX) {
        s->operator[++s->top] = elem;
    }
}

void popChar(StackChar* s) {
    if(s->top >= 0) {
        s->top--;
    }
}

char topChar(StackChar* s) {
    if(s->top >= 0) {
        return s->operator[s->top];
    }
    
    return 0;
}

bool isEmptyChar(StackChar* s) {
    if(s->top == -1)
        return true;
    
    return false;
}


typedef struct {
    int type;
    char str[32];
}Token;

Token tokens[MAX];
int nr_token;

void getToken(char* s) {
    int iter_s = 0;
    
    nr_token = 0;
    
    while (s[iter_s] != '\0') {
        if (s[iter_s] == ' ')
            iter_s++;
        else if (s[iter_s]<'0' || s[iter_s]>'9'){
            strncpy(tokens[nr_token].str, &s[iter_s], 1);
            tokens[nr_token++].type = s[iter_s++];
        }
        else {
            int posDigit = 0;
            tokens[nr_token].type = 0;
            while (s[iter_s] && !(s[iter_s]<'0' || s[iter_s]>'9'))
                tokens[nr_token].str[posDigit++] = s[iter_s++];
            tokens[nr_token++].str[posDigit] = 0;
        }
    }
}

bool cmpPrinority(char op1, char op2) {
    if (op1 == '+' || op1 == '-')
        return false;
    else if(op2 == '+' || op2 == '-')
        return true;
    
    return false;
}

typedef struct {
    int isNum;
    char str[32];
}Op;

Op expr[MAX];
int nr_expr;

void getRevPolish() {
    StackChar s={.top=-1};
    int posToken = 0;

    nr_expr = 0;
    
    while (posToken < nr_token) {
        switch (tokens[posToken].type) {
            case 0:
                expr[nr_expr].isNum = 1;
                strcpy(expr[nr_expr++].str, tokens[posToken++].str);
                break;
            case '(':
                pushChar(&s,tokens[posToken++].str[0]);
                break;
            case ')':
                {
                    char c;
                    while (c=topChar(&s),popChar(&s),c!='(') {
                        expr[nr_expr].isNum = 0;
                        strncpy(expr[nr_expr++].str,&c,1);
                    }
                    posToken++;           
                    break;
                }
            default:
                {
                 while (1) {
                        if(isEmptyChar(&s) || topChar(&s)=='(') {
                        pushChar(&s,tokens[posToken++].str[0]);
                        break;
                        }
                        else if(cmpPrinority(tokens[posToken].str[0], topChar(&s))) {
                            pushChar(&s,tokens[posToken++].str[0]);
                            break;
                        }
                        else{
                            char c=topChar(&s);
                            popChar(&s);
                            expr[nr_expr].isNum = 0;
                            strncpy(expr[nr_expr++].str,&c,1);
                        }
                    }
                }
                            
        }
    }
    while (!isEmptyChar(&s)) {
        char c=topChar(&s);
        popChar(&s);
        expr[nr_expr].isNum = 0;
        strncpy(expr[nr_expr++].str,&c,1);
    }
}

int eval() {
    int posExpr = 0;
    StackInt s={.top=-1};
    
    while (posExpr < nr_expr) {
        if (expr[posExpr].isNum == 1) {
            int num = atoi(expr[posExpr++].str);
            pushInt(&s,num);
        }
        else {
            int num2 = topInt(&s);
            popInt(&s);
            int num1 = topInt(&s);
            popInt(&s);
            switch (expr[posExpr++].str[0]) {
                case '+':
                    num1 += num2;
                    break;
                case '-':
                    num1 -= num2;
                    break;
                case '*':
                    num1 *= num2;
                    break;
                case '/':
                    num1 /= num2;
                    break;
            }
            pushInt(&s,num1);
        }
    }
    
    return topInt(&s);
}

int calculate(char* s) {
    getToken(s);
    // for(int i=0; i<nr_token; i++)
    //     printf("%s\t%d\n",tokens[i].str,tokens[i].type);
    // puts("-----------\n");
    getRevPolish();
    // for(int i=0; i<nr_expr; i++)
    //     printf("%s ",expr[i].str);
    // puts("\n-----------\n");
    return eval();
}

解法二:
在这里插入图片描述

#define MAX 1000000

typedef struct {
    int type;
    char str[32];
}Token;

Token tokens[MAX];
int nr_token;

void getToken(char* s) {
    int iter_s = 0;
    
    nr_token = 0;
    
    while (s[iter_s] != '\0') {
        if (s[iter_s] == ' ')
            iter_s++;
        else if (s[iter_s]<'0' || s[iter_s]>'9')
            tokens[nr_token++].type = s[iter_s++];
        else {
            int posDigit = 0;
            tokens[nr_token].type = 0;
            while (s[iter_s] && !(s[iter_s]<'0' || s[iter_s]>'9'))
                tokens[nr_token].str[posDigit++] = s[iter_s++];
            tokens[nr_token++].str[posDigit] = 0;
        }
    }
}

bool check_parentheses(Token *p,Token *q){
	int count = 0;
	int sign = 0;

	for (Token *iter_p=p;iter_p<q;iter_p++) {
		if (iter_p->type=='(')
			count++;
		else if (iter_p->type==')')
			count--;
		if (count==0)
			sign=1;
	}
	if (q->type==')')
		count--;
	if (sign==0 && count==0 && (p->type=='(' && q->type==')'))
		return true;
	return false;
}
   
Token* pos_mop(Token *p, Token *q){
	int is_inP = 0;
    int sign = 0; 
	Token *pos_mod = NULL;

	for (Token *iter_p=p; iter_p<=q; iter_p++) {
		if (iter_p->type == '(') {
			is_inP++;
			continue;
		}
		if (iter_p->type == ')') {
			is_inP--;
			continue;
		}
		if (is_inP != 0) continue;
		if (iter_p->type!='+' && iter_p->type!='-' 
		   && iter_p->type!='*' && iter_p->type!='/')
			continue;
        if (sign<=1 && (iter_p->type=='+' || iter_p->type=='-')){
			pos_mod = iter_p;
			sign = 1;
		}
		else if (sign<=0 && (iter_p->type=='*' || iter_p->type=='/'))
			pos_mod = iter_p;
	}

	return pos_mod;
}

int eval(Token *p, Token *q){
    if (p == q) 
        return atoi(p->str);	
  	else if (check_parentheses(p, q ) == true)
    	return eval(p + 1, q - 1);
  	else {
		Token *op = pos_mop(p, q);
		int val1 = eval(p, op - 1);
		int val2 = eval(op + 1, q);
		switch (op->type) {
			case '+': return val1 + val2;
			case '-': return val1 - val2;
			case '*': return val1 * val2;
			case '/': return val1 / val2;
    	}
	}
	return 0;
}


int calculate(char* s) {
    getToken(s);
    return eval(tokens,&tokens[nr_token-1]);
}

解法三:
在这里插入图片描述

#define MAX 1000000

int val[MAX];
int sign[MAX];
int top_val;
int top_sign;

void eval(char op) {
    if (op == '+')
        val[top_val-1] = val[top_val-1] + val[top_val];
    else if (op == '-')
        val[top_val-1] = val[top_val-1] - val[top_val];
    top_val--;
}

int calculate(char* s) {
    int pos = 0;

    top_val = -1;
    top_sign = -1;
    
    while (s[pos] != '\0') {
        if (s[pos] == ' ')
            pos++;
        else if (s[pos] >= '0' && s[pos] <= '9') {
            int num = 0;
            while (s[pos] != '\0' && s[pos] >= '0' && s[pos] <= '9') {
                num *= 10;
                num +=  s[pos++] - '0';
            }
            val[++top_val] = num;
        }
        else {
            if (s[pos] == ')') {
                while (sign[top_sign--] != '(')
                     eval(sign[top_sign+1]);
            }
            else if (top_sign == -1 || sign[top_sign] == '(' || s[pos] == '(')
                sign[++top_sign] = s[pos];
            else {
                eval(sign[top_sign]);
                sign[top_sign] = s[pos];
            }
            pos++;
        }
    }
    while (top_sign != -1)
        eval(sign[top_sign--]);
    
    return val[0];
}

227. Basic Calculator II—Medium

题目

Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero.

思路

解法一、二为表达式求值通解,参照上题解法一、二。
解法三:
针对本题具体解法

AC代码
解法一:
在这里插入图片描述
解法二:
在这里插入图片描述
解法三:
在这里插入图片描述

#define MAX 1000000

int val[MAX];
int sign[MAX];
int top_val;
int top_sign;

void eval(char op) {
    switch (op) {
        case '+':  val[top_val-1] += val[top_val];break;
        case '-':  val[top_val-1] -= val[top_val];break;
        case '*':  val[top_val-1] *= val[top_val];break;
        case '/':  val[top_val-1] /= val[top_val];break;
    }
    top_val--;
}

int calculate(char* s) {
    int pos = 0;
    
    top_val = -1;
    top_sign = -1;
    
    while (s[pos] != '\0') {
        if (s[pos] == ' ') 
            pos++;
        else if (s[pos] >= '0' && s[pos] <= '9') {
            int num = 0;
            while (s[pos] != '\0' && s[pos] >= '0' && s[pos] <= '9') {
                num *= 10;
                num += s[pos++] - '0';
            }
            val[++top_val] = num;
        }
        else if (top_sign == -1 || ((sign[top_sign] == '+' || sign[top_sign] == '-')
                 && (s[pos] == '*' || s[pos] == '/')))
            sign[++top_sign] = s[pos++];
        else if (s[pos] == '*' || s[pos] == '/'){
            eval(sign[top_sign]);
            sign[top_sign] = s[pos++];
        }
        else {
            while (top_sign != -1)
                eval(sign[top_sign--]);
        }
    }
    while (top_sign != -1)
        eval(sign[top_sign--]);
    
    return val[0];
}

84. Largest Rectangle in Histogram—Hard

题目

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
在这里插入图片描述
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
在这里插入图片描述
The largest rectangle is shown in the shaded area, which has area = 10 unit.

思路

解法一:
维护一个最大面积值,初值为0;便利所有 bar,对于每个 bar,向两边遍历,到边界处或者到小于该 bar 值的地方停止,统计便利的个数,计算 Area,更新最大面积值。
解法二:
显然这个时间复杂度比较高,我们试着优化;
想到,同一个查找区域覆盖下的等高bar,不需要再次遍历,所有设标志,直接剪去
解法三:
这个是网上非常流行的一种巧妙解法。
构造一个递增栈,栈中每个元素是 heights 的下标,栈底就是左边界;遍历时,若当前元素小于栈顶元素,则该元素就是右边界。
对于每个新元素:
若栈为空或大于等于栈顶元素,直接入栈;
若小于栈顶元素,则该元素为右边界,然后出栈,其左边界有两种可能:栈非空,则该元素与当前栈顶位置差值,为左边界;栈空,则左边界为 heights 的最左边减一;然后更新最大面积值。记得最后栈非空,相当于当前元素是最小元素,执行确定左边界操作。

AC代码
解法一:
在这里插入图片描述

int largestRectangleArea(int* heights, int heightsSize) {
    int maxArea = 0;
    
    for (int i = 0; i < heightsSize; i++) {
        int leftCount = 0;
        for (int j = i - 1; j >= 0 && heights[j] >= heights[i]; j--)
            leftCount++;
        int rightCount = 0;
        for (int j = i + 1; j < heightsSize && heights[j] >= heights[i]; j++)
            rightCount++;
        int currArea = (leftCount + rightCount + 1) * heights[i];
        if (currArea > maxArea)
            maxArea = currArea;
    }
    
    return maxArea;
}

解法二:
在这里插入图片描述

int largestRectangleArea(int* heights, int heightsSize) {
    int maxArea = 0;
    int sign[heightsSize+1];
    
    memset(sign, -1, sizeof(sign));
    
    for (int i = 0; i < heightsSize; i++) {
        if (sign[i] == 0) continue;
        int leftCount = 0;
        for (int j = i - 1; j >= 0 && heights[j] >= heights[i]; j--)
            leftCount++;
        int rightCount = 0;
        for (int j = i + 1; j < heightsSize && heights[j] >= heights[i]; j++) {
            if ( heights[j] == heights[i])
                sign[j] = 0;
            rightCount++;
        }
        int currArea = (leftCount + rightCount + 1) * heights[i];
        if (currArea > maxArea)
            maxArea = currArea;
    }
    
    return maxArea;
}

解法三:
在这里插入图片描述

int largestRectangleArea(int* heights, int heightsSize) {
    int st[heightsSize+1];
    int top = -1;
    int maxArea = 0;
    int currArea;
    int pos = 0;
    
    while (pos < heightsSize) {
        if (top == -1 || heights[st[top]] <= heights[pos])
            st[++top] = pos++;
        else {
            int currPos = st[top--];
            if (top == -1)
                currArea = heights[currPos] * pos;
            else 
                currArea = heights[currPos] * (pos - st[top] - 1);
            if (currArea > maxArea) 
                maxArea = currArea;
        }
    }
    while ( top > -1) {
        int currPos = st[top--];
        if (top == -1)
            currArea = heights[currPos] * pos;
        else 
            currArea = heights[currPos] * (pos - st[top] - 1);
        if (currArea > maxArea) 
            maxArea = currArea;
    }
    
    return maxArea;
}

猜你喜欢

转载自blog.csdn.net/weixin_43758823/article/details/86547357
今日推荐