每周刷题第三期

2024-05-24 12:36
文章标签 刷题 每周 第三期

本文主要是介绍每周刷题第三期,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

个人主页:星纭-CSDN博客

系列文章专栏:Python

踏上取经路,比抵达灵山更重要!一起努力一起进步! 

目录

题目一:环形链表

题目二:删除有序数组中的重复项

题目三:有效的括号

题目四:用队列实现栈

题目五:用栈实现队列 


题目一:环形链表

题目出处:. - 力扣(LeetCode)/

题目描述:这道题和上一期的环形链表很像只不过,一个是判断是否存在环,一个是求入环节点。

题解思路:采用双指针。定义两个指针fast,slow,fast一次走两步,slow一次走一步。

然后我们来分析一下这道题的数学关系。 

相遇点指的是fast指针和slow指针第一次相遇的地方。

当fast和slow相遇的时候,fast行走的距离是slow的两倍,

slow:L + X

fast:2(L + X) = L + X + a * N。a指的是fast进入环后行走的圈数

L = (a - 1) * N + N - X;

N-X就是相遇点到环的距离。也就是说,如果fast从相遇出发,slow从起点出发,均每次走一步。两者第一次相遇的地方就是进入环的节点。

struct ListNode *detectCycle(struct ListNode *head) {struct ListNode*fast = head,*slow = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(fast == slow){fast = head;while(fast != slow){fast = fast->next;slow = slow->next;				}return fast;}}return NULL;
}

题目二:删除有序数组中的重复项

题目出处:. - 力扣(LeetCode) 

题目描述:给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

这道题的要求是,原地删除,所以空间复杂度是O(1),因为这个数组是非严格递增的,重复的元素是挨在一起的,即相等的元素在数组中一定是连续的。

解题思路:使用双指针,定义两个指针src,dst.src表示下一个不同元素的下标,dst表示要填入的位置的下标。

dst开始指向0,src开始指向1.如果src和dst相同,src就加1。不相同,dst加1,然后移动元素,然后src也加1.

int removeDuplicates(int* nums, int numsSize) {int src,dst;src = 1;dst = 0;while(src < numsSize){if(nums[src] != nums[dst]){++dst;nums[dst] = nums[src];++src;}else{src++;}}int k = dst + 1;return k;
}

题目三:有效的括号

题目出处:. - 力扣(LeetCode)

题目描述 :

这个题目的示例不够全面, 

对于字符串s = "{[]}",这样的字符串也成立,s = "()[{}]"也是成立的,题目所给的示例会让人误以为匹配的括号必须连续,其实不是这样的,这是题目的一个问题。

题目思路:首先需要用C语言手动实现一个栈。

然后我们开始遍历整个字符串:当遇到左括号的时候,就入栈,遇到右括号的时候,就取出栈顶元素,进行匹配,如果不匹配说明这个字符串不有效,反之继续匹配 ,直到结束,该字符串就匹配。关于栈的代码参考前面的文章。

bool isValid(char* s) {Stack st;STInit(&st);while (*s) {if (*s == '(' || *s == '[' || *s == '{') {STPush(&st, *s);} else {if (IsEmpty(&st)) {STDestory(&st);return false;} else {char ch = STTop(&st);STPop(&st);if ((ch == '(' && *s != ')') || (ch == '[' && *s != ']') ||(ch == '{' && *s != '}')) {STDestory(&st);return false;}}}++s;}bool ret = IsEmpty(&st);STDestory(&st);return ret;
}

在每次使用return语句之前都要销毁这个栈,避免内存泄漏。

最后为什么是返回ret?

如果遇到这样的字符,不难发现根本没有进入循环,直接返回了true,这明显是不正确的,所以需要进行判断,栈是否为空,如果为空,所以左括号并没匹配完成,这个字符串无效。

题目四:用队列实现栈

题目出处:. - 力扣(LeetCode)

题目描述:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

 解题思路:

如果接下来我们要进行出栈,根据先进后出的规则,那么得到的第一个数据应该是5,可是仅仅在队列一中进行出队列入队列是达不到这样的效果的。

那么如何进行操作呢?

首先我们可以将1-4入队列到队列二中,这样队列一中就只剩下一个数据5了,此时出队列就是5.起到了先进后出的效果。如果还需要放入数据,很明显是放在队列二中,因为此时的队列一已经没有了数据了。

首先需要使用C语言实现一个队列。代码参考前面的文章。

初始化:

typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* pst = (MyStack*)malloc(sizeof(MyStack));QueueInit(&(pst->q1));QueueInit(&(pst->q2));return pst;
}

push:


void myStackPush(MyStack* obj, int x) {if (!QueueEmpty(&(obj->q1))) {QueuePush(&(obj->q1), x);} else {QueuePush(&(obj->q2), x);}
}

新放入的数据,需要放在已经存放有数据的队列。如果两个队列都为空,那么此时随便放在那个队列中都可以。

删除数据:

int myStackPop(MyStack* obj) {Queue* noempty = &(obj->q1);Queue* empty = &(obj->q2);if (!QueueEmpty(&(obj->q2))) {noempty = &(obj->q2);empty = &(obj->q1);}while (QueueSize(noempty) > 1) {QueuePush(empty, QueueFront(noempty));QueuePop(noempty);}int top = QueueFront(noempty);QueuePop(noempty);return top;
}

由于不确定,哪一个队列是空的,所以采用假设法进行判断,出数据的时候,需要将非空队列的数据的前n-1个全部转移到空队列中,留剩下一个出栈即可。

查看栈顶元素:

int myStackTop(MyStack* obj) {if (!QueueEmpty(&(obj->q2))) {return QueueBack(&(obj->q2));} else {return QueueBack(&(obj->q1));}
}

实现的队列中是,含有查看队尾元素的,非空的队列的队尾元素就是栈顶元素。 

判空与销毁:

bool myStackEmpty(MyStack* obj) {return QueueEmpty(&(obj->q1)) && QueueEmpty(&(obj->q2));
}void myStackFree(MyStack* obj) {QueueDestory(&(obj->q1));QueueDestory(&(obj->q2));free(obj);
}

这里的判空,是判断两个队列都是否为空。

题目五:用栈实现队列 

 题目出处;. - 力扣(LeetCode)

 题目描述:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

解题思路:

这道题与上一道题类似

只不过,需要判断空了,入栈的时候只需要把 数据固定存放在一个栈中,push栈,出栈的时候,先出pop栈中的数据,如果栈为空,把push栈的数据导过来。

初始化:

typedef struct {ST pushst;ST popst;
} MyQueue;MyQueue* myQueueCreate() {MyQueue*obj = (MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->pushst);STInit(&obj->popst);return obj;
}

入数据:

void myQueuePush(MyQueue* obj, int x) {STPush(&obj->pushst,x);
}

查看数据:

int myQueuePeek(MyQueue* obj) {if(STEmpty(&obj->popst)){while(!STEmpty(&obj->pushst)){STPush(&obj->popst,STTop(&obj->pushst));STPop(&obj->pushst);}}return STTop(&obj->popst);
}

首先需要判断popst中是否为空,如果不为空就直接返回即可,为空,就需要向pust中得到数据。

 出数据:

int myQueuePop(MyQueue* obj) {int front = myQueuePeek(obj);STPop(&obj->popst);return front;
}

出数据,直接使用peek函数先查看一下栈顶有没有元素,有才出,否则peek元素会先导数据。

判空与销毁:

bool myQueueEmpty(MyQueue* obj) {return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
}void myQueueFree(MyQueue* obj) {STDestory(&obj->popst);STDestory(&obj->pushst);free(obj);
}

这篇关于每周刷题第三期的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/998425

相关文章

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

GitHub每周最火火火项目(9.2-9.8)

项目名称:polarsource / polar 项目介绍:polar 是一个开源项目,它是 Lemon Squeezy 的替代方案,并且具有更具优势的价格。该项目的目标是为开发者提供一种更好的选择,让他们能够在追求自己的热情和兴趣的同时,通过编码获得相应的报酬。通过使用 polar,开发者可以享受到更实惠的价格,同时也能够更自由地发挥自己的创造力和技能。 项目地址:https://github.

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II 1.题目 1.1递增子序列 题目链接:491. 非递减子序列 - 力扣(LeetCode) 视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0491.%E9%80%92%E

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II 1.题目 1.1复原IP地址 题目链接:93. 复原 IP 地址 - 力扣(LeetCode) 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0093.%E5%A4%8

【笔记】数据结构刷题09

快速排序 215. 数组中的第K个最大元素 class Solution {public:int findKthLargest(vector<int>& nums, int k) {return divide(nums,0,nums.size()-1,nums.size()-k);}int divide(vector<int>& nums,int left,int right,int k)

C语言:刷题日志(1)

一.阶乘计算升级版 本题要求实现一个打印非负整数阶乘的函数。 其中n是用户传入的参数,其值不超过1000。如果n是非负整数,则该函数必须在一行中打印出n!的值,否则打印“Invalid input”。 首先,知道阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。那么我们先来个简单的阶乘计算吧。 #include<stdio.h>int Fact(int n){if (n <=

【每日刷题】Day112

【每日刷题】Day112 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 1137. 第 N 个泰波那契数 - 力扣(LeetCode) 2. 面试题 08.01. 三步问题 - 力扣(LeetCode) 3. LCR 088. 使用最小花费爬楼梯 - 力扣(LeetCode) 1. 1137. 第 N 个泰波那契数 - 力扣(LeetCo

深度学习每周学习总结N9:transformer复现

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 目录 多头注意力机制前馈传播位置编码编码层解码层Transformer模型构建使用示例 本文为TR3学习打卡,为了保证记录顺序我这里写为N9 总结: 之前有学习过文本预处理的环节,对文本处理的主要方式有以下三种: 1:词袋模型(one-hot编码) 2:TF-I

【数据结构】【java】leetcode刷题记录--链表

简介 链表是一种常见的基础数据结构,它由一系列节点组成,每个节点包含数据域和指向下一个节点的指针。在Java中,链表通常用于实现动态数据结构,因为它可以根据需要动态地增加或减少节点。 链表简介: 节点结构:链表中的每个元素称为节点(Node),每个节点包含两部分:数据域(存储数据)和指针域(存储下一个节点的地址)动态性:链表的长度不是固定的,可以根据需要动态地增减节点。内存分配:链表中的节点