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

链表数组OJ题汇总

前言: 

在计算机科学中,数组和链表是两种常见的数据结构,用于存储和组织数据。它们分别具有不同的特点和适用场景。

本博客将深入讨论数组和链表在OJ题目中的应用。我们将从基本概念开始,介绍数组和链表的定义和特点,并分析它们在不同场景下的优势和劣势。

接下来,我们将探讨数组在OJ题目中的常见应用。我们将介绍如何原地移除数组中所有的val元素,如何删除排序数组中的重复项,以及如何合并两个有序数组。

随后,我们将探讨链表在OJ题目中的常见应用。我们将介绍如何删除链表中值为val的所有节点,如何翻转单链表,如何返回链表的中间结点和倒数第k个结点,以及如何合并两个有序链表等。

此外,我们还将介绍一些更复杂的链表问题,如链表的分割、回文链表、相交链表、带环链表等。我们将详细讲解每个问题的解题思路和实现方法。

最后,我们将讨论带有随机指针的链表,介绍如何复制这种特殊的链表结构,并解决相关问题。

通过对这些数组和链表的OJ题目的探讨,我们将加深对数组和链表的理解,并学会在实际问题中灵活运用它们。希望本博客能帮助读者更好地掌握这两种数据结构,并提升解题能力。让我们开始吧!

个人主页:Oldinjuly的个人主页

收录专栏:数据结构

欢迎各位点赞👍收藏⭐关注❤️


目录

🌹一、数组

💐1.原地移除数组中所有的val元

💐2.删除排序数组中的重复项

💐3.合并两个有序数组

🌹二、链表

💐1.删除链表中值为val的所有节点

💐2.翻转单链表

💐3.返回中间结点

💐4.返回倒数第k个结点

💐6.链表分割

💐 7.回文链表

💐8.相交链表

💐9.带环链表Ⅰ

💐10.带环链表Ⅱ

💐11.复制带随机指针的链表


🌹一、数组

💐1.原地移除数组中所有的val元素


 方法一:暴力删除,挪动数据覆盖: 时间复杂度O(N^2), 空间复杂度O(1)

方法二:开辟新空间tmp,设置两个“指针”dst和src,nums[src]不等于val的直接插入到tmp[dst]中,等于val的直接跳过,然后tmp拷贝到nums中。

int removeElement(int* nums, int numsSize, int val)
{int* tmp = (int*)malloc(sizeof(int)*numsSize);int dst=0,src=0;while(src<numsSize){if(nums[src]!=val){tmp[dst++]=nums[src++];}else{src++;}}memcpy(nums,tmp,sizeof(int)*dst);return dst;
}

方法三:双指针在原数组上直接覆盖

nums[src]不等于val,直接覆盖尾插到dst位置,++dst,++src。

nums[src]等于val,直接++src,相当于删除。

 

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

💐2.删除排序数组中的重复项


双指针dst和src:

dst和src如果相等,src++。

dst和src如果不相等,dst先++,然后src覆盖到dst上,src再++。

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

💐3.合并两个有序数组


1.从前往后归并,需要开新空间

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{int* tmp = (int*)malloc(sizeof(int)*(m+n));int begin1=0, begin2=0, pos=0;while(begin1 < m && begin2 < n){if(nums1[begin1] < nums2[begin2]){tmp[pos++]=nums1[begin1++];}else{tmp[pos++]=nums2[begin2++];}}while(begin1 < m){tmp[pos++]=nums1[begin1++];}while(begin2 < n){tmp[pos++]=nums2[begin2++];}memcpy(nums1,tmp,sizeof(int)*(m+n));free(tmp);
}

2.从后往前归并,不需要开新空间

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{int end1=m-1,end2=n-1,end=m+n-1;while(end1>=0&&end2>=0){if(nums1[end1]>nums2[end2]){nums1[end--]=nums1[end1--];}else{nums1[end--]=nums2[end2--];}}while(end2>=0){nums1[end--]=nums2[end2--];}
}

🌹二、链表

💐1.删除链表中值为val的所有节点


解法一:在原链表上进行操作

struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* cur = head;struct ListNode* prev = NULL;while(cur){if(cur->val == val){if(cur == head){head = cur->next;free(cur);cur = head;}else{prev->next = cur->next;free(cur);cur = prev->next;}}else{prev = cur;cur = cur->next;}}return head;
}

注意:头删不需要prev节点,是要单独讨论的。


解法二:创建一个新链表

struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* newhead = NULL, *tail = NULL, *cur = head;while(cur){if(cur->val == val){struct ListNode* next = cur->next;free(cur);cur = next; }else {if(newhead == NULL){newhead = cur;tail = cur;}else{tail->next = cur;tail = tail->next;}cur = cur->next;}}if(tail){tail->next = NULL;}return newhead;
}

注意:

  • 逻辑上的一个新链表,但是内存没有额外开辟空间。
  • 避免每次重复找尾结点,设置一个tail指针变量来记录。
  • 最后要给tail的next置空。

💐2.翻转单链表


解法一:三指针链接法

struct ListNode* reverseList(struct ListNode* head)
{struct ListNode *n1, *n2, *n3;n1 = NULL;n2 = head;if(head)n3 = head->next;while(n2){n2->next = n1;n1 = n2;n2 = n3;if(n3)n3 = n3->next;} return n1;
}

问题:为什么设置三个指针变量进行迭代?

如果只设置两个指针变量进行迭代,n1赋值n2的next域之后,n2就无法迭代带原本的next域,而三个指针变量可以解决这个问题。

注意:n3进行迭代之前要判断n3是否为NULL。


解法二:头插法

struct ListNode* reverseList(struct ListNode* head)
{struct ListNode* newhead = NULL;struct ListNode* cur = head;while(cur){struct ListNode* next = cur->next;cur->next = newhead;newhead = cur;cur = next;}return newhead;
}

💐3.返回中间结点


双指针(快慢指针):fast指针走两步,slow指针走一步

奇数个链表节点:fast == NULL,slow对应中间结点

偶数个链表结点:fast->next == NULL,slow对应中间节点

struct ListNode* middleNode(struct ListNode* head)
{struct ListNode *slow = head, *fast = head;while(fast && fast->next){fast = fast->next->next;slow = slow->next;}return slow;
}

💐4.返回倒数第k个结点


双指针:

fast指针先走k步,然后两个指针一起走,fast走到NULL,slow走到目标节点。

fast指针先走k-1步,然后两个指针一起走,fast走到尾结点,slow走到目标节点。

struct ListNode* getKthFromEnd(struct ListNode* head, int k)
{struct ListNode *fast = head, *slow = head;int i = 0;for(i=0;i<k;i++) {//链表没有k步长,那么倒数就是空if(!fast)return NULL;fast = fast->next;}/*while(k--)//k--走k步,--k走k-1步{if(!fast)return NULL;fast = fast->next;}*/while(fast){fast = fast->next;slow = slow->next;}return slow;
}

💐5.合并两个有序链表


struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{struct ListNode *head = NULL, *tail = NULL;if(!list1)return list2;if(!list2)return list1;while(list1 && list2){if(list1->val < list2->val){if(head == NULL){head = list1;tail = list1;}else{tail->next = list1;tail= tail->next;}list1 = list1->next;}else{if(head == NULL){head = list2;tail = list2;}else{tail->next = list2;tail= tail->next;}list2 = list2->next;}}if(list1){tail->next = list1;}if(list2){tail->next = list2;  }return head;
}

注意:

  • while循环的条件是list1&&list2,循环里面是继续条件,但是我们心中想的是循环终止条件,也就是有一个链表结束循环也就结束。
  • 当循环结束后,只需要把 没有遍历到空的链表尾接到tail后面即可。

这题合并有序链表和合并有序数组都使用了一个关键思想:归并,这也是排序算法的一个重要思想。


代码优化:

这里的归并使用了尾插,不带头结点单链表的尾插有一个缺点,就是第一次插入不需要找tail,直接赋值给head即可,需要单独讨论;为了使代码简洁,此时就需要另一种链表:带头结点(哨兵位)的单链表

头结点什么数据也不存储,那么这个头结点有什么意义呢?

  • 尾插尾删不需要单独讨论,形成统一化。
  • 不需要传二级指针了,改的是头结点的next,修改结构体,直接传结构体指针即可。
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{if(!list1)return list2;if(!list2)return list1;struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* tail = head;while(list1 && list2){if(list1->val < list2->val){tail->next = list1;tail = tail->next;list1 = list1->next;}else{tail->next = list2;tail = tail->next;list2 = list2->next;}}if(list1)tail->next = list1;if(list2)tail->next = list2;struct ListNode* next = head->next;free(head);head = next;return head;
}

💐6.链表分割


class Partition {
public:ListNode* partition(ListNode* pHead, int x) {ListNode *lHead, *lTail, *gHead, *gTail;lHead = lTail = (ListNode*)malloc(sizeof(ListNode));gHead = gTail = (ListNode*)malloc(sizeof(ListNode));ListNode* cur = pHead;while(cur){if(cur->val < x){lTail->next = cur;lTail = lTail->next;}else{gTail->next = cur;gTail = gTail->next;}cur = cur->next;}lTail->next = gHead->next;//不置空,可能会出现环gTail->next = NULL;ListNode* next = lHead->next;free(lHead);free(gHead); return next; }
};

注意:

  • 该题开辟了两个链表头结点:lessHead,greaterHead,lessHead存放比x小的节点,greaterHead存放大于等于x的节点。
  • 这题最好使用带头结点的单链表,原因:如果不带头结点,lessHead为空或者greaterHead为NULL的话,此时链接两个链表lTail->next = gHead->next这句代码就会出错。
  • greaterTail的next的要置空,否则会出现环。

💐 7.回文链表


思路:

对于链表1->2->3->2->1->NULL;想判断是否回文,可以先将链表后半部分3->2->1->NULL进行逆置变成1->2->3->NULL;然后前半部分和后半部分进行比较,全部相等就是回文链表。 

这里要复用之前的两个题目的函数:返回中间节点翻转单链表


struct ListNode* middleNode(struct ListNode* head)
{struct ListNode *slow = head, *fast = head;while(fast && fast->next){fast = fast->next->next;slow = slow->next;}return slow;
}struct ListNode* reverseList(struct ListNode* head)
{struct ListNode* newhead = NULL;struct ListNode* cur = head;while(cur){struct ListNode* next = cur->next;cur->next = newhead;newhead = cur;cur = next;}return newhead;
}bool isPalindrome(struct ListNode* head)
{struct ListNode* headA = head;struct ListNode* headB = middleNode(head);struct ListNode* curA = headA;struct ListNode* curB = reverseList(headB);;while(curA && curB){if(curA->val != curB->val)return false;curA = curA->next;curB = curB->next;}return true;
}

💐8.相交链表


补充:相交链表

上一道题目回文链表中,后半部分逆置过后的链表其实就是相交链表。

相交链表是这样的:

 

 而不是这样:


解法一:暴力遍历,headA的每一个节点都和headB的每一个节点比较(比较的是节点指针,不能比较val),时间复杂度O(N^2)。

解法二:

先遍历两个链表得到两个链表的长度,先判断尾结点是否相等,如果不相等一定不是相交链表;

再算出长度差,让长的先走长度差步,然后一起走,第一个相等的就是公共结点。


struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{struct ListNode *curA = headA, *curB = headB;int lenA = 1, lenB = 1;while(curA->next)//这里是为了找到尾结点,所以len初始化成1{curA = curA->next;lenA++;}  while(curB->next){curB = curB->next;lenB++;}//不相交if(curA != curB)return NULL;  int dis = abs(lenA - lenB);struct ListNode *longList = headA, *shortList = headB;if(lenA < lenB){longList = headB;shortList = headA;}while(dis--){longList = longList->next;}while(longList != shortList){longList = longList->next;shortList = shortList->next;}return longList;
}

💐9.带环链表Ⅰ


 这题也可以用快慢指针来解决:

fast指针:一次走两步

slow指针:一次走两步

在两个指针都进环后,他们在环中的某个位置一定能相遇!为什么呢?这要用相对运动的思想来分析一下了:

  •  我们可以把带环链表进行抽象化,便于分析:

 

 

  • 首先fast指针一定比slow指针先入环:

 

  • slow指针入环后,fast指针开始追赶slow指针,只是典型的追击问题,假设slow入环后两者距离为N。

 

  • slow走一步,fast走两步,每追击一次,两者的距离缩短1。两者的距离变化:N->N-1->N-2->...->1->0
  • 综上,两者的距离最终为0,会相遇。
bool hasCycle(struct ListNode *head) 
{struct ListNode *fast = head, *slow = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(fast == slow)return true;  }return false;   
}

思考:如果fast一次走三步、四步?他们会在环中相遇吗?

答案是不一定!

分析:

所以:初始距离M和C-1均为奇数的话,他们永不相遇!fast一次走四步也是一样的道理,综上fast最好的步数就是两步。 

💐10.带环链表Ⅱ

 


 解法一:需要一些数学知识来分析:

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

解法二:相交链表法 

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{struct ListNode *curA = headA, *curB = headB;int lenA = 1, lenB = 1;while(curA->next)//这里是为了找到尾结点,所以len初始化成1{curA = curA->next;lenA++;}  while(curB->next){curB = curB->next;lenB++;}//不相交if(curA != curB)return NULL;  int dis = abs(lenA - lenB);struct ListNode *longList = headA, *shortList = headB;if(lenA < lenB){longList = headB;shortList = headA;}while(dis--){longList = longList->next;}while(longList != shortList){longList = longList->next;shortList = shortList->next;}return longList;
}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){struct ListNode* meet = slow;struct ListNode* newhead = meet->next;meet->next = NULL;return getIntersectionNode(head,newhead);}}   return NULL;
}

💐11.复制带随机指针的链表


分析:所谓深拷贝,就是malloc出新的节点,然后把原始结点的数据赋值到新结点中。并且新链表随机指针的链接关系要和原链表的链接关系相同。

方法一:首先拷贝原链表的结点得到一个新链表,然后记录每个结点和他random域结点的相对位置,或者给每个节点设置一个索引值。通过相对位置来调整新链表的random域的链接关系。(注意:一定不能通过原链表的random域的值来进行链接,否则拷贝链表中的指针会指向原链表中。)

时间复杂度:O(N^2)

方法二:让拷贝结点插入到原节点的后面,然后置每个拷贝节点的random域,最后把拷贝结点给解下来并恢复原链表。

struct Node* copyRandomList(struct Node* head) 
{//拷贝结点插入到原节点的后面struct Node* cur = head;while(cur){struct Node* next = cur->next;struct Node* copy = (struct Node*)malloc(sizeof(struct Node));copy->val = cur->val;cur->next = copy;copy->next = next;cur = next;} //置一下拷贝节点的random域cur = head;while(cur){struct Node* copy = cur->next;if(cur->random == NULL){copy->random = NULL;}else{copy->random = cur->random->next;}cur = copy->next;}//把拷贝结点尾插下来,并且恢复原结点cur = head;struct Node *copyhead = NULL, *copytail = NULL;while(cur){struct Node *copy = cur->next, *next = copy->next;//copy节点尾插到新链表if(copyhead == NULL){copyhead = copytail =copy;}else{copytail->next = copy;copytail = copytail->next;}//恢复原链表cur->next = next;cur = next;}return copyhead;
}

相关文章:

链表数组OJ题汇总

前言&#xff1a; 在计算机科学中&#xff0c;数组和链表是两种常见的数据结构&#xff0c;用于存储和组织数据。它们分别具有不同的特点和适用场景。 本博客将深入讨论数组和链表在OJ题目中的应用。我们将从基本概念开始&#xff0c;介绍数组和链表的定义和特点&#xff0c;并…...

中间人攻击与 RADIUS 身份验证

在数字时代&#xff0c;中间人&#xff08;MitM&#xff09;攻击已成为一种日益严重的威胁。根据网络安全风险投资公司的网络安全统计数据&#xff0c;预计到2025年&#xff0c;网络犯罪每年将给世界造成10.5万亿美元的损失&#xff0c;比2015年的3万亿美元大幅增加。这种令人震…...

虚拟机安装国产操作系统的方法

1.这里以银河麒麟为例&#xff0c;其他以liunx为基础的国产操作系统都是一样的方法。 2.下载操作系统如下&#xff08;选第一个就行&#xff09;&#xff1a; 任选其一下载&#xff1a; 3.安装虚拟机软件(这里以virtualbox为例&#xff0c;vmare也是一样都可以) 4.打开虚拟机…...

【Linux】云服务器自动化部署VuePress博客(Jenkins)

前言 博主此前是将博客部署在 Github Pages&#xff08;基于 Github Action&#xff09;和 Vercel 上的&#xff0c;但是这两种部署方式对于国内用户很不友好&#xff0c;访问速度堪忧。因此将博客迁移到自己的云服务器上&#xff0c;并且基于 Jenkins&#xff08;一款开源持续…...

Golang字符串处理深入解析:探索 strings 标准库的全部方法

Golang 的 strings 标准库提供了许多用于处理字符串的函数。以下是一些主要的方法&#xff1a; Contains(s, substr string) bool: 检查字符串是否包含子串。ContainsAny(s, chars string) bool: 检查字符串是否包含字符集中的任何字符。ContainsRune(s string, r rune) bool:…...

如何在群辉NAS系统下安装cpolar套件,并使用cpolar内网穿透?

如何在群辉NAS系统下安装cpolar套件,并使用cpolar内网穿透&#xff1f; 文章目录 如何在群辉NAS系统下安装cpolar套件,并使用cpolar内网穿透&#xff1f;前言1. 在群辉NAS系统下安装cpolar套件2. 管理隧道列表3. 创建固定数据隧道 前言 群晖作为大容量存储系统&#xff0c;既可…...

opencv基础57-模板匹配cv2.matchTemplate()->(目标检测、图像识别、特征提取)

OpenCV 提供了模板匹配&#xff08;Template Matching&#xff09;的功能&#xff0c;它允许你在图像中寻找特定模板&#xff08;小图像&#xff09;在目标图像中的匹配位置。模板匹配在计算机视觉中用于目标检测、图像识别、特征提取等领域。 以下是 OpenCV 中使用模板匹配的基…...

搜索插入位置

题目描述&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target …...

Centos Linux快速复制文件并查看进度的方法(保留文件原始时间戳等属性)

用cp命令保证快速复制&#xff0c;screen保证不丢失你对cp命令执行情况的掌控。 需要用到screen软件包&#xff0c;防止复制过程中终端被关闭。 centos linux直到7默认都没有screen&#xff0c;需要安装一下 普通账户&#xff1a; sudo yum -y install screen root账户&am…...

牛奶产业链的工业“链主品牌”利乐是如何诞生的?

瑞典的利乐公司&#xff0c;一个在乳品产业链中占据重要地位的“链主品牌”&#xff0c;通过提供创新的包装材料和解决方案&#xff0c;在全球范围内占据了显著的市场份额。利乐从不生产一滴奶&#xff0c;却赚取了中国乳业 75%的利润&#xff0c;一年创收超过 800 亿人民币。在…...

【历史上的今天】8 月 11 日:苹果电脑之父诞生;阿里巴巴收购雅虎中国;OpenAI 击败电竞世界冠军

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 8 月 11 日&#xff0c;在 1999 年的今天&#xff0c;欧亚一些地区观赏到了一次壮丽的日全食景象。这次日全食是本世纪最后一次日全食&#xff0c;将持续两分钟…...

Flutter 报错 Could not create task ‘xxx‘.this and base files have different roots

遇到此问题也是先去百度了&#xff0c;有的说改了Gradle版本、gradle-wrapper.properties版本和ext.kotlin_version版本之后解决的&#xff0c;我没尝试&#xff0c;我用蹩脚的英语大致读了一下就不是这样说的&#xff0c;况且我用有道翻译了也不是这个意思啊&#xff0c;我不知…...

单调递增的数字——力扣738

文章目录 题目描述解法题目描述 解法 #include<iostream> #include<string>using namespace std;int monotoneIncreasingDigits...

STL文件格式详解【3D】

STL&#xff08;StereoLithography&#xff1a;立体光刻&#xff09;文件是 3 维表面几何形状的三角形表示。 表面被逻辑地细分或分解为一系列小三角形&#xff08;面&#xff09;。 每个面由垂直方向和代表三角形顶点&#xff08;角&#xff09;的三个点来描述。 切片算法使用…...

【分布式技术专题】RocketMQ延迟消息实现原理和源码分析

痛点背景 业务场景 假设有这么一个需求&#xff0c;用户下单后如果30分钟未支付&#xff0c;则该订单需要被关闭。你会怎么做&#xff1f; 之前方案 最简单的做法&#xff0c;可以服务端启动个定时器&#xff0c;隔个几秒扫描数据库中待支付的订单&#xff0c;如果(当前时间-订…...

Qt中ffmpeg API存储和显示摄像头视频

Qt中ffmpeg API存储和显示摄像头视频的功能需要之前写的视频ffmpegAPI的视频播放的流程。 代码源码位置&#xff1a;https://download.csdn.net/download/qq_43812868/88157743?spm1001.2014.3001.5503 一、存储和显示摄像头的视频的流程 这是读取打开视频文件的流程&#x…...

jfinal tomcat部署

首先明确一下 JFinal 项目是标准的 java web 项目&#xff0c;其部署方式与普通 java web 项目没有任何差别。Java Web 项目在 Tomcat 下部署有一些不必要的坑需要避免&#xff0c;所以撰写此文方便大家绕过一些坑&#xff0c;以下部署以 linux 为例&#xff0c;windows 与此类…...

Linux - MongoDB 数据库自动退出服务问题/闪退

问题&#xff1a;MongoDB 自动退出服务问题 原因&#xff1a; 由于 Mongodb 服务&#xff0c;使用过多系统内存&#xff0c;导致系统强制停止 Mongodb 服务。 解决方法&#xff1a; 在 mongodb.conf 配置文件内&#xff0c;添加新配置内容&#xff1a; wiredTigerCacheSi…...

B2B2C多语言电商系统平台搭建,多用户商城系统搭建(app、小程序、微商城)

搭建B2B2C多语言电商系统平台以及多用户商城系统&#xff08;包括app、小程序、微商城&#xff09;的步骤如下&#xff1a; 步骤一&#xff1a;需求分析和规划 1. 确定项目的目标和范围。明确平台所需的功能、支持的语言、用户权限等要求。 2. 分析竞争对手&#xff0c;并确定…...

【MySQL】创建高级联结

目录 一、使用表别名 二、使用不同类型的联结 1.自联结 2.自然联结 3.外部联结 3.使用带聚集函数的联结 4.使用联结和联结条件 一、使用表别名 别名除了用于列名和计算字段外&#xff0c;SQL还允许给表名起别名。 起别名有两个好处&#xff1a; 一个是缩短SQL语句&am…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...