当前位置: 首页 > news >正文

算法打卡第10天

33 重复的子字符串

(力扣459题)

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成

解题思路

题目要求判断一个字符串是否可以通过重复其子串来构造。核心思路是利用 KMP 算法中的前缀表(next 数组)来判断。

  1. 计算前缀表
    • 使用 KMP 算法的 getNext 函数计算字符串 s 的前缀表。前缀表的每个位置 next[i] 表示字符串 s 的前 i+1 个字符中,最长相同前后缀的长度。
    • 通过遍历字符串,利用已计算的前缀表值逐步构建完整的前缀表。
  2. 判断重复子串
    • 如果字符串长度 len 能被 (len - next[len - 1]) 整除,说明字符串可以由长度为 (len - next[len - 1]) 的子串重复构成。
    • next[len - 1] 表示整个字符串的最长相同前后缀长度,如果该长度不为零且满足上述条件,则返回 true,否则返回 false
  3. 特殊情况处理
    • 如果字符串为空,直接返回 false

代码

#include <iostream>
using namespace std;class Solution
{
public:// KMP算法void getNext(int *next, const string &s){    // 前缀表next[0] = 0;// 前缀表末尾int j = 0;for(int i = 1; i < s.size(); i++){//前后缀不同while(j > 0 && s[i] != s[j]){// 回退j =  next[j - 1];   }//前后缀相同if(s[i] == s[j]){j++;}//  更新nextnext[i] = j;}}bool   repeatedSubstringPattern(string s){if(s.size() == 0){return 0;}int next[s.size()];getNext(next, s);int len = s.size();if(next[len - 1] != 0 && len % (len - (next[len - 1])) == 0){return true;}return false;}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

34.用栈实现队列

(力扣232题)

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

实现 MyQueue 类:

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

说明:

  • 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

提示:

  • 1 <= x <= 9
  • 最多调用 100pushpoppeekempty
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

进阶:

  • 你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。

解题思路

使用栈来模拟队列的行为,如果仅仅用一个栈,是一定不行的,需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系

  1. push 操作:直接将元素压入 stIN 栈。
  2. pop 操作:如果 stOut 栈为空,将 stIN 栈的所有元素依次弹出并压入 stOut 栈。这样,stOut 栈的栈顶元素就是队列的首元素。然后弹出并返回该元素。
  3. peek 操作:与 pop 类似,但需要将弹出的元素重新压入 stOut 栈,以保持队列状态不变。
  4. empty 操作:判断两个栈是否都为空,如果都为空,则队列为空。
class MyQueue
{
public:stack<int> stIN;stack<int> stOut;MyQueue(){}// 元素压入stIn栈void push(int x){stIN.push(x);}// 队列前面移除元素并返回该元素int pop(){// 如果输出栈为空if (stOut.empty()){// 将输入栈中的所有元素转移到输出栈while (!stIN.empty()){// 将输入栈的栈顶元素压入输出栈stOut.push(stIN.top());// 弹出输入栈的栈顶元素stIN.pop();}}// 获取输出栈的栈顶元素(即队列的首元素)int result = stOut.top();// 弹出输出栈的栈顶元素stOut.pop();// 返回队列的首元素return result;}int peek(){// 获取队列前面的元素,但不移除他int res = this->pop();//  因为pop函数弹出了元素res,所以再添加回输出栈stOut.push(res);// 返回队列的首元素return res;}// 判断队列是否为空bool empty(){// 当输入栈和输出栈都为空时,队列为空return stIN.empty() && stOut.empty();} 
};
  • 时间复杂度: 都为O(1)。pop和peek看起来像O(n),实际上一个循环n会被使用n次,最后还是O(1)。
  • 空间复杂度: O(n)

35.用队列实现栈

(力扣255题)

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

实现 MyStack 类:

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

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsizeis empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
  • 解题思路

    1. push 操作
      • 直接将元素压入队列的末尾。这个操作与队列的 push 方法一致。
    2. poptop 操作
      • 为了模拟栈的 poptop 操作,需要将队列的最后一个元素(即栈顶元素)移到队列的前面。
      • 通过将队列的前 size-1 个元素依次弹出并重新添加到队列尾部,使得最后一个元素移到队列的前面。
      • 对于 pop 操作,弹出并返回队列的队首元素。
      • 对于 top 操作,获取队首元素后,再将其重新加回到队列尾部,以保持队列的原始状态。
    3. empty 操作
      • 直接检查队列是否为空。如果队列为空,返回 true;否则返回 false
  1. push 操作
    • 直接将元素压入队列的末尾。这个操作与队列的 push 方法一致。
  2. poptop 操作
    • 为了模拟栈的 poptop 操作,需要将队列的最后一个元素(即栈顶元素)移到队列的前面。
    • 通过将队列的前 size-1 个元素依次弹出并重新添加到队列尾部,使得最后一个元素移到队列的前面。
    • 对于 pop 操作,弹出并返回队列的队首元素。
    • 对于 top 操作,获取队首元素后,再将其重新加回到队列尾部,以保持队列的原始状态。
  3. empty 操作
    • 直接检查队列是否为空。如果队列为空,返回 true;否则返回 false

代码

#include <iostream>
#include <queue>
using namespace std;
/*请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。*/
class MyStack
{
public:queue<int> que;MyStack(){}// 将元素 x 推到队列的末尾void push(int x){que.push(x);}// 移除并返回栈顶元素int pop(){int size = que.size();size--;// 将队列头部的元素(除了最后一个元素外) 弹出再重新添加到队列尾部while (size--){que.push(que.front());que.pop();}// 此时弹出的元素顺序就是栈的顺序了int result = que.front();que.pop();return result;}// 返回栈顶元素。int top(){int size = que.size();size--;// 将队列头部的元素(除了最后一个元素外) 弹出再重新添加到队列尾部while(size--){que.push(que.front());que.pop();}// 此时弹出的元素顺序就是栈的顺序了int result = que.front();//将获取完的元素也重新添加到队列尾部,保证数据结构没有变化que.push(que.front());que.pop();return result;}//如果栈是空的,返回 true ;否则,返回 false bool empty(){return que.empty();}
};/*** Your MyStack object will be instantiated and called as such:* MyStack* obj = new MyStack();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->top();* bool param_4 = obj->empty();*/
  • 时间复杂度: pop为O(n),top为O(n),其他为O(1)
  • 空间复杂度: O(n)

相关文章:

  • 磁盘管理无法删除卷,虚拟磁盘管理器:不支持该请求
  • STM32 HAL库函数学习 GPIO篇
  • Kotlin中的::操作符详解
  • Kotlin 中集合遍历有哪几种方式?
  • Kotlin委托机制使用方式和原理
  • 再见Notepad++,你好Notepad--
  • MATLAB语言教程:从入门到精通的全面指南
  • 【HarmonyOS 5】鸿蒙应用px,vp,fp概念详解
  • ES中must与filter的区别
  • Elasticsearch的集群管理介绍
  • ElasticSearch简介及常用操作指南
  • django项目开启debug页面操作有数据操作记录
  • Starrocks 物化视图的实现以及在刷新期间能否读数据
  • 记一次 Starrocks be 内存异常宕机
  • R语言在生物群落数据统计分析与绘图中的实践应用
  • 拉取gitlab项目
  • 零基础设计模式——结构型模式 - 代理模式
  • YOLO12改进-模块-引入AFE模块 增强模型对复杂场景(如杂乱背景、小目标、半透明物体)的特征提取能力
  • python2解决反编译乱码
  • 数值计算与数据相关参数剖析:保障模型训练稳定与准确
  • 郑州网站制作免费/58同城如何发广告
  • 导购个人网站怎么做的/外链代发软件
  • 卢松松网站/互联网营销师是哪个部门发证
  • 0基础怎么做网站模版/seo线上培训班
  • 网站开发的实验心德/seo裤子的关键词首页排名有哪些
  • 怎样建设论坛网站/网络营销的作用