10.18--一下午连肝20道leetcode题(纯C实现)

Posted C_YCBX Py_YYDS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.18--一下午连肝20道leetcode题(纯C实现)相关的知识,希望对你有一定的参考价值。

题目

20.有效的括号

155.最小栈

225.用队列实现栈

232.用栈实现队列

234.回文链表

844.比较含退格的字符

682.棒球比赛

1047. 删除字符串中的所有相邻重复项

1441.用栈构建数组

1475.商品折扣后的最终价格

1544.整理字符串

1598. 文件夹操作日志搜集器

1614. 括号的最大嵌套深度

150. 逆波兰表达式求值

735. 行星碰撞

1.两数之和

167. 两数之和 II - 输入有序数组

806. 写字符串需要的行数

821. 字符的最短距离

832. 翻转图像

解题代码与分析

20.有效的括号

很简单的栈的运用题,通过左右括号的限制栈的入和出。

bool checkL(char x){
    return x=='('||x=='{'||x=='[';
}
bool checkR(char x){
    return x==')'||x=='}'||x==']';
}
bool isMatch(char a,char b){
    switch(a){
        case '(':
            return b==')';
        case '{':
            return b=='}';
        case '[':
            return b==']';
    }
    return false;
}
bool isValid(char * s){
    int n = strlen(s);
    int top = 0;//这里top指向stack的长度
    char stack[10005];
    for(int i=0;i<n;i++){
        if(checkL(s[i])){
            stack[top++] = s[i];
        }else if(checkR(s[i])){
            if(top==0)
                return false;
            if(isMatch(stack[top-1],s[i]))
                top--;
            else return false;
        }
    }
    return top==0;
}

155.最小栈

我的做法很朴素,保持最小元素在栈顶即可,只需要对每次入栈操作特殊处理,当栈为空的时候只需要入一个元素,如果栈不为空,则对当前要入的元素进行判断,得出更小的一个元素,然后多入一个元素到栈顶,也就是这个更小的元素,这样也就相当于除了最开始情况下是入一个,其余情况都是两个两个的入栈,所以每次出栈除了最开始的一个情况外都需要 -= 2

#define SIZE 15000
typedef struct {
    int nums[SIZE];
    int top;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() {
  MinStack* obj = malloc(sizeof(MinStack));
  obj->top = -1;
  return obj;
}
//重点就在于push和pop的处理
void minStackPush(MinStack* obj, int val) {
    //当栈空时只入一个,其他情况将栈顶与入栈元素进行比较,保持最小的元素在栈顶,入栈元素在栈顶的下一个。
    if(obj->top==-1)
    obj->nums[++(obj->top)] = val;
    else{
        int min = obj->nums[obj->top]>val?val:obj->nums[obj->top];
        obj->nums[++(obj->top)] = val;
        obj->nums[++(obj->top)] = min; 
    }
}

void minStackPop(MinStack* obj) {
    //若到了最后一个元素,则底下没有其他东西垫底需要特殊处理。
    //当栈为空则top不动。
    if(obj->top==-1){
        return;
    }
    //确保top指向最小值
    if(obj->top==0){
        obj->top=-1;
        return;
    }
    obj->top-=2;
}
//关键就在于能改变top指针的操作的设计,而下面两个不能影响top指针,所以很是简单。。
int minStackTop(MinStack* obj) {
    if(obj->top==0){
        return obj->nums[obj->top];
    }
    return obj->nums[obj->top-1];
}

int minStackGetMin(MinStack* obj) {
    return obj->nums[obj->top];
}

void minStackFree(MinStack* obj) {
    free(obj);
}

225.用队列实现栈

用C语言的话,只要对队列的实现较为熟悉应该都好做,我们需要两个队列实现一个栈的话,需要能够熟练的运用好这两个队列,其中一个队列我们作为中转站,也就是,每次如果要执行栈的pop得到栈顶,则我们需要不断的对队列进行pop,然后转移到另一个中转站,直到只剩一个元素,则这个就是栈顶元素,返回这个元素即可。上面这些描述是对栈的pop和top操作中都需要做的操作,以下就是有一些不一样了:
对于pop操作:进行上述操作后,我们需要再把中转站变成要操作的队列(指针交换),注意还需要把这剩下的最后一个元素pop。
对于top操作:进行上述操作后,需要再执行一次push操作,然后再指针交换。

  • 结合代码进行观看体验更佳。
#define MAXLEN 20
typedef struct{
    int* date;
    int front;
    int rear;
}queue;
typedef struct {
    queue* Q1;
    queue* Q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* res = (MyStack*)malloc(sizeof(MyStack));
    res->Q1 = (queue*) malloc(sizeof(queue));
    res->Q2 = (queue*) malloc(sizeof(queue));
    res->Q1->date = (int*)malloc(sizeof(int)*MAXLEN);
    res->Q2->date = (int*)malloc(sizeof(int)*MAXLEN);
    res->Q1->front = res-> Q1->rear = res->Q2->front = res->Q2->rear = 0;
    return res;
}

void myStackPush(MyStack* obj, int x) {
    obj->Q1->date[obj->Q1->rear%MAXLEN] = x;//一个栈负责入
    obj->Q1->rear++;
}

int myStackPop(MyStack* obj) {
    while((obj->Q1->front+1)%MAXLEN != (obj->Q1->rear)%MAXLEN){//把队列push到另外一个队列,只剩下一个元素为止
        obj->Q2->date[obj->Q2->rear%MAXLEN] = obj->Q1->date[obj->Q1->front%MAXLEN];
        obj->Q2->rear++,obj->Q1->front++;
    }
    //交换指针内容
    queue* t = obj->Q1;
    obj->Q1 = obj->Q2;
    obj->Q2 = t;
    return obj->Q2->date[obj->Q2->front++];
}

int myStackTop(MyStack* obj) {
    while((obj->Q1->front+1)%MAXLEN != (obj->Q1->rear)%MAXLEN){//把队列push到另外一个队列,只剩下一个元素为止
        obj->Q2->date[obj->Q2->rear%MAXLEN] = obj->Q1->date[obj->Q1->front%MAXLEN];
        obj->Q2->rear++,obj->Q1->front++;
    }
    int res = obj->Q1->date[obj->Q1->front];
    obj->Q2->date[obj->Q2->rear%MAXLEN] = obj->Q1->date[obj->Q1->front%MAXLEN];
    obj->Q2->rear++,obj->Q1->front++;
    //交换指针内容
    queue* t = obj->Q1;
    obj->Q1 = obj->Q2;
    obj->Q2 = t;
    return res;
}

bool myStackEmpty(MyStack* obj) {
    return obj->Q1->front == obj->Q1->rear;
}

void myStackFree(MyStack* obj) {
    free(obj->Q1->date);
    obj->Q1->date = NULL;
    free(obj->Q2->date);
    obj->Q2->date = NULL;
    free(obj->Q1);
    obj->Q1 = NULL;
    free(obj->Q2);
    obj->Q2 = NULL;
    free(obj);
    obj = NULL;
}

232.用栈实现队列

用栈实现队列,单纯的是利用另外一个栈来实现倒序的功能,使得末端变首端,需要注意的是我们只需要一个队列用于push,另一个队列用于 pop 和 front 即可,完全不需要中转站这种操作,需要注意只有当用于 pop 和 front的栈空了,才需要重新补给!

/* 两个栈实现队列, S1,S2          */
/* 入队操作: push元素进入S1       */
/* 出队操作: S2非空时, 从S2弹出元素, S2为空, S1数据导入S2再弹出 */
#define MAXLEN 20
typedef struct{
    int* date;
    int top;
}stack;
typedef struct {
    stack* S1;
    stack* S2;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* Q = (MyQueue*)malloc(sizeof(MyQueue));
    Q->S1 = (stack*)malloc(sizeof(stack));Q->S2 = (stack*)malloc(sizeof(stack));
    Q->S1->date = (int*)malloc(sizeof(int)*MAXLEN); 
    Q->S2->date = (int*)malloc(sizeof(int)*MAXLEN);
    Q->S1->top = Q->S2->top = 0;
    return Q;
}
/* push元素时, 只往S1中push */
void myQueuePush(MyQueue* obj, int x) {
    obj->S1->date[obj->S1->top++] = x;
}
/* pop元素时, S2非空时, 弹出; S2为空, S1数据导入S2中, 继续从S2弹出数据 */
int myQueuePop(MyQueue* obj) {
    if((obj->S2->top)>0)
        return obj->S2->date[--(obj->S2->top)];
    while(obj->S1->top > 0){
        obj->S2->date[obj->S2->top] = obj->S1->date[--(obj->S1->top)];
        obj->S2->top++;
    }
    return obj->S2->date[--(obj->S2->top)];
}

int myQueuePeek(MyQueue* obj) {
    if((obj->S2->top)>0)
        return obj->S2->date[(obj->S2->top)-1];
    while(obj->S1->top > 0){
        obj->S2->date[obj->S2->top] = obj->S1->date[--(obj->S1->top)];
        obj->S2->top++;
    }
    return obj->S2->date[obj->S2->top-1];
}

bool myQueueEmpty(MyQueue* obj) {
    return obj->S1->top == 0&&obj->S2->top==0;
}

/* 释放申请的空间 */
void myQueueFree(MyQueue* obj) {    
    free(obj->S1->date);
    obj->S1->date = NULL;
    free(obj->S2->date);
    obj->S2->date = NULL;
    free(obj->S1);
    obj->S1 = NULL;
    free(obj->S2);
    obj->S2 = NULL;
    free(obj);
    obj = NULL;
}

234.回文链表

链表题乱入😀

typedef struct ListNode ListNode;

ListNode* getHalf(ListNode* head) {

    ListNode* fast = head;

    ListNode* slow = head;

    while (fast->next != NULL && fast->next->next != NULL) {

        fast = fast->next->next;

        slow = slow->next;

    }

    return slow;

}
ListNode* reverseList(ListNode* head) {

    ListNode* prev = NULL;

    ListNode* curr = head;

    while (curr != NULL) { //不断的切断再重组的方式不断迭代形成反转

        ListNode* nextTemp = curr->next;

        curr->next = prev;

        prev = curr;

        curr = nextTemp;

    }

    return prev; //返回逆序后的头指针

}
bool isPalindrome(struct ListNode* head) {

    if (head == NULL) {

        return true;
    }



    // 找到前半部分链表的尾节点并反转后半部分链表

    ListNode* half = getHalf(head);

    ListNode* secondHalfStart = reverseList(half->next);



    // 判断是否回文

    ListNode* p1 = head;

    ListNode* p2 = secondHalfStart;

    bool result = true;

    while (result && p2 != NULL) {

        if (p1->val != p2->val) {

            result = false;

        }

        p1 = p1以上是关于10.18--一下午连肝20道leetcode题(纯C实现)的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 最常见的150道前端面试题(简单题下)

漫话算法[二分查找](上):一首诗解决5道LeetCode题

leetcode 最常见的 150 道前端面试题(简单题上)

LeetCode 20. 有效的括号

LeetCode刷题计划

LeetCode刷题计划