本学期出现问题拾遗

本学期出现问题拾遗


本文仅用于记录自身在本学期的学习过程中所存在的问题,借此劝诫自身好好学习!

周报3.17

关于kmp算法:

void calculateNext(char *pattern, int *next, int len) {
    int i = 0, j = -1;
    next[0] = -1;

    while (i < len - 1) {
        if (j == -1 || pattern[i] == pattern[j]) {
            i++;
            j++;
            next[i] = j;
        } else {
            j = next[j];//出现问题
        }
    }
}

问题

在求取kmp算法中的next数组时,对于j指针的回溯不够了解,在自己进行实现的时候,当字符串不匹配的时候,直接将j赋值为0,少考虑了,当当前后缀与前缀不匹配时,后缀还有可能与之前的前缀相匹配。

解决方法

KMP算法之求next数组代码讲解

巩固

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

代码实现

void GetNext(int* next, char* s, int len){
    int i = 0, j = -1;
    next[0] = -1;
    while (i < len - 1) {
		if(j == -1 || s[i] == s[j]){
            i++;
            j++;
            next[i] = j;
        } else {
            j = next[j];
        }
    }
}
int strStr(char* haystack, char* needle) {
    int len1 = strlen(haystack);
    int len2 = strlen(needle);
    int next[len2];
    GetNext(next, needle, len2);
    int j = 0, i = 0;
    while (i < len1 && j < len2) {
        if (j == -1 || haystack[i] == needle[j]) {
            i++;
            j++;
        } else {
            j = next[j];  // 失配时,模式串右移
        }
        if(j == len2){
            return i - j;
        }
    }
    return -1;
}

周报3.24

问题

关于栈与队列

能通过c语言实现队列和栈,但是对于栈和队列用c语言结构互相实现的理解还不够到位

关于回溯算法

在回溯算法中,关于for循环嵌套递归的理解不够到位,导致无法很好的理解题目,并进行代码实现。

解决方法

用栈实现队列

用队列实现栈

回溯算法

巩固

用栈实现队列

​ 用栈模拟队列,本质上就是涉及两个栈的协同工作。我们可以通过将元素推入一个栈(称为入栈操作),然后从该栈中弹出元素并推入另一个栈(称为出栈操作),以实现队列的先进先出(FIFO)顺序。

  1. 入队列操作
    • 当需要向队列中添加一个元素时,将元素推入第一个栈(称为入栈操作)。
  2. **出队列操作:
    • 如果第二个栈为空,则将第一个栈中的所有元素弹出并推入第二个栈,然后从第二个栈中弹出元素(称为出栈操作)。
    • 如果第二个栈不为空,则直接从第二个栈中弹出元素。

代码:


typedef struct {
    int* stk;
    int stkSize;
    int stkCapacity;
} Stack;

Stack* stackCreate(int cpacity) {
    Stack* ret = malloc(sizeof(Stack));
    ret->stk = malloc(sizeof(int) * cpacity);
    ret->stkSize = 0;
    ret->stkCapacity = cpacity;
    return ret;
}

void stackPush(Stack* obj, int x) {
    obj->stk[obj->stkSize++] = x;
}

void stackPop(Stack* obj) {
    obj->stkSize--;
}

int stackTop(Stack* obj) {
    return obj->stk[obj->stkSize - 1];
}

bool stackEmpty(Stack* obj) {
    return obj->stkSize == 0;
}

void stackFree(Stack* obj) {
    free(obj->stk);
}


typedef struct {
    Stack* in;
    Stack* out;
} MyQueue;


MyQueue* myQueueCreate(){
    MyQueue* q =malloc(sizeof(MyQueue));
    q->in = stackCreate(100);
    q->out = stackCreate(100);
    return q;
}

void InToOut(MyQueue* q) {
    while(!stackEmpty(q->in)) {
        stackPush(q->out, stackTop(q->in));
        stackPop(q->in);
    }
}
void myQueuePush(MyQueue* obj, int x) {
    stackPush(obj->in, x);
}

int myQueuePop(MyQueue* obj) {
    if(stackEmpty(obj->out)){
        InToOut(obj);
    }
    int x = stackTop(obj->out);
    stackPop(obj->out);
    return x;
}

int myQueuePeek(MyQueue* obj) {
    if (stackEmpty(obj->out)) {
        InToOut(obj);
    }
    return stackTop(obj->out);
}

bool myQueueEmpty(MyQueue* obj) {
    return stackEmpty(obj->in) && stackEmpty(obj->out);
}

void myQueueFree(MyQueue* obj) {
    stackFree(obj->in);
    stackFree(obj->out);
}


用队列实现栈

我们使用了循环队列实现栈的后进先出(LIFO)的顺序。

  1. **入栈操作 **:

    • 入栈操作将元素添加到队列的末尾(rear 指针指向的位置)。
  2. **出栈操作 **:

    • 出栈操作首先计算队列中实际的元素数量。
    • 然后将队列中除了最后一个元素外的其他元素重新排列,使得原来的最后一个元素被移到队列的前端。
    • 最后,弹出队列的第一个元素(现在是原来的最后一个元素)作为栈顶元素。
  3. **获取栈顶元素操作 **:

    • 直接返回队列中最后元素的值。
  4. 这段程序使用队列来实现栈的基本操作,即入栈(push)、出栈(pop)、获取栈顶元素(top)以及判断栈是否为空(empty)。虽然使用队列来实现栈不是常见的方法,但这段代码展示了一种可能的实现方式。

    以下是该程序如何使用队列实现栈的方法:

    1. 数据结构
      • 定义了一个结构体 MyStack,其中包含一个大小为 100 的数组 queue 作为队列的底层数据结构。
      • 使用两个指针 frontrear 分别指示队列的前端和后端。
    2. 入栈操作 (myStackPush)
      • 入栈操作将元素添加到队列的末尾(rear 指针指向的位置)。
    3. 出栈操作 (myStackPop)
      • 出栈操作首先计算队列中实际的元素数量。
      • 然后将队列中除了最后一个元素外的其他元素重新排列,使得原来的最后一个元素被移到队列的前端。
      • 最后,弹出队列的第一个元素(现在是原来的最后一个元素)作为栈顶元素。
    4. 获取栈顶元素操作 (myStackTop)
      • 直接返回队列中倒数第二个元素的值。
    5. 判断栈是否为空操作 (myStackEmpty)
      • 如果队列的前端指针和后端指针相等,则队列为空,栈也为空。
    6. 释放栈内存 (myStackFree)
      • 释放 MyStack 结构体占用的内存。
typedef struct {
    int queue[100];
    int front;
    int rear;
} MyStack;

MyStack* myStackCreate() {
    MyStack* stack = malloc(sizeof(MyStack));
    stack->front = 0;
    stack->rear = 0;
    return stack;
}

void myStackPush(MyStack* obj, int x) {
    obj->queue[(obj->rear)++] = x;
}

int myStackPop(MyStack* obj) {
    int rear = obj->rear;
    int front = obj->front;
    int size = rear - front;
    while (size-- > 1) {
        obj->queue[rear++] = obj->queue[front++];
    }
    int top = obj->queue[front++];
    obj->front = front;
    obj->rear = rear;
    return top;
}

int myStackTop(MyStack* obj) {
    return obj->queue[(obj->rear) - 1];
}


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

void myStackFree(MyStack* obj) {
    obj->front = 0;
    obj->rear = 0;
}

[回溯算法](77. 组合 - 力扣(LeetCode))

class Solution {
public:
    vector<int> temp;
    vector<vector<int>> ans;
    void dfs(int curr, int n, int k) {
        if((temp.size() - curr + n + 1) < k) {
            return;
        }
        if(temp.size() == k) {
            ans.push_back(temp);
            return;
        }
        temp.push_back(curr);
        dfs(curr + 1, n, k);
        temp.pop_back();
        dfs(curr + 1, n, k);
    }
    vector<vector<int>> combine(int n, int k) {
        dfs(1, n, k);
        return ans;
    }
};

周报3.31

问题

学习了单调栈的相关算法,但对在遇到较为复杂问题,即遇到所求的内容不能直接反映出与栈的单调存储关系的题目,很难判断选用单调递增栈还是单调递减栈。

解决方法

《代码随想录》算法视频公开课

多刷题,对单调栈进行更深的理解,下面会进行博客的撰写以巩固自己的学习程度。

巩固

LCR 038. 每日温度

题目较为直白,就是找出当前元素在数组中下一个比其更大的元素,要是没有就返回0,那么就是使用单调递减栈,栈中存储温度的下标,遇到比栈顶元素还大的元素就将栈顶元素出栈,并返回求取出栈元素下标于当前元素下标的差值。

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n = temperatures.size();
        vector<int> ans(n);
        stack<int> s;
        for (int i = 0; i < n; i++) {
            while (!s.empty() && temperatures[i] > temperatures[s.top()]) {
                int temp = s.top();
                ans[temp] = i - temp;
                s.pop();
            }
            s.push(i);
        }
        return ans;
    }

};

42. 接雨水

本题也是使用单调递减栈的题目,由于我们想知道当前高度能否接到雨水,那就是要找到左边第一个高于它的,和右边第一个高于它的,若都能找得到那么就说明该位置能接住雨水,左右两边高度最小值再减去当前位置的高度,不断进行累加,就能求出该答案。在这道题里我们不需要去判断,栈中的剩余内容,因为当栈中还存有元素时,说明它的右边没有比它更高的物体,存不住水。

class Solution {
public:
    int trap(vector<int>& height) {
        int sum = 0;
        int n = height.size();
        stack<int> s;
        int width = 0, temp = 0, h = 0;
        for (int i = 0;i < n; i++) {
            while (!s.empty() && height[i] > height[s.top()]) {
                int temp = s.top();
                s.pop();
                if (s.empty()) break;
                int width = i - s.top() - 1;
                int h = min(height[s.top()], height[i]) - height[temp];
                sum += h * width;
            }
            s.push(i);
        }
        return sum;
    }
};

84. 柱状图中最大的矩形

这道题就是使用单调递增栈完成的题目,我们要求出能圈出的最大的矩形面积,其实要找到左边第一个大于栈顶元素的矩形,和右边第一个大于栈顶元素,因为只有两边都大于当前栈顶元素,矩形的高度才会是当前栈顶的高度,不断遍历,找到最大的区域。与接雨水不同,我们还需要判断栈是否为空,当栈不为空时我们就将其循环弹出,将弹出元素作为左边界,将heights的最后一个元素作为右边界,计算矩形大小。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> s;
        int n = heights.size();
        int max_area = 0;
        for (int i = 0; i < heights.size(); i++) {
            while (!s.empty() && heights[i] < heights[s.top()]) {
                int temp = s.top();
                s.pop();
                int width = (s.empty())? i : i - s.top() - 1;
                max_area = max(max_area, (width * heights[temp]));
            }
            s.push(i);
        }
        while (!s.empty()) {
                int temp = s.top();
                s.pop();
                int width = (s.empty())? n : n - s.top() - 1;
                max_area = max(max_area, (width * heights[temp]));
            }
        return max_area;
    }
};

想说的话

​ 在每周的学习中,我们应该及时总结自身在学习过程中发生的问题,并对其进行深入分析和思考。如果我们忽视了这些问题,可能会导致学习效率的降低,以及对知识的理解和掌握程度的减弱。因此,对于每个出现的问题,我们应该及时记录下来,并思考它们的根源、解决方案以及可能的改进方法。

​ 借此机会,劝诫自己戒骄戒躁,端正学习态度,及时修正自身行为,不应因为自身的怠惰而忽视对问题的发现和总结,希望自己能够永怀谦卑之心,在学习路上走的更远。

是故无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。行衢道者不至,事两君者不容。目不能两视而明,耳不能两听而聪。螣蛇无足而飞,鼫鼠五技而穷。《诗》曰:“尸鸠在桑,其子七兮。淑人君子,其仪一兮。其仪一兮,心如结兮!”故君子结于一也。

  • 30
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值