2024年C C++最新单链表C语言实现附加力扣题_c 力扣 遍历 单链表(1),2024年最新C C++面试项目源码

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

	tail->next = newNode;
}

}


**传递一级指针无法改变main函数的plist的指针,因为是在不同的栈帧中开辟的,只是一份值拷贝,互不影响,所以传递二级指针**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0972bd67b4824d1e9a7af9f1151cede6.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)


### 头插


![请添加图片描述](https://img-blog.csdnimg.cn/5282cc729e0b4076b863edb8578a4304.gif)



> 
> 头插只需要创建一个新的结点newNode,让新的结点链接ps,再让ps去做新的头,由于需要改变外面的指针,还是要传递二级指针,头插即使是面对链表为空还是不会受影响
> 
> 
> 



//头插
void SLTPushFront(SLTNode **ps,int x)
{
SLTNode *newNode = BuySLTNode(x);
newNode->next = ps;
//ps去做新的头
*ps = newNode;
}


### 头删


![请添加图片描述](https://img-blog.csdnimg.cn/cd88846a922c47c19fe5cfdaf7b133b3.gif)



> 
> 头删同样需要改变外面的指针,所以要传二级,移除第一个结点,让第二个结点做新的头
> 
> 
> 



//头删
void SLTPopFront(SLTNode **ps)
{
if (*ps == NULL)
return;
SLTNode *delNode = *ps;
*ps = delNode->next;
free(delNode);
delNode = NULL;
}


### 尾删


![请添加图片描述](https://img-blog.csdnimg.cn/116bef0bd5874f84bcfcd6e930a039bc.gif)



> 
> 尾删需要考虑三种情况  
>  1、表为空,不需要删除,直接返回  
>  2、只剩一个结点,删除这个结点,再置空,也需要改变外面指针的指向,必须传二级指针  
>  3、有多个结点,定义前驱指针prev,和目标指针cur,当cur指向最后一个结点的时候释放cur,cur置空,前驱指针prev指向空
> 
> 
> 



//尾删
void SLTPopBack(SLTNode **ps)
{

SLTNode \*phead = \*ps;
//只有一个结点
if (phead->next == NULL)
{
	free(phead);
	\*ps = NULL;
	phead = NULL;
}
//表为空直接返回
else if (\*ps == NULL) 
{
	return ;
}
//剩多个结点
else 
{	
	//定义前驱指针和目标指针
	SLTNode \*tail= \*ps;
	SLTNode \*prev = NULL;
	
	while (tail->next != NULL)
	{
		prev = tail;
		tail= tail->next;
	}
	//移除最后一个结点,让前一个指针指向空
	free(tail);
	cur = NULL;
	prev->next = NULL;
}

}


### 查找


查找54  
 ![请添加图片描述](https://img-blog.csdnimg.cn/b6b3ef6d4b624443828a2f4b2fafd0b3.gif)



> 
> 找到该结点就返回,没找到就返回空,空表直接返回
> 
> 
> 



//查找
SLTNode* SLTFind(SLTNode *ps, int x)
{
if (ps == NULL)
return NULL;
SLTNode *cur = ps;
while (cur != NULL)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}


### 指定位置后插入



> 
> 在pos后面插入一个新的结点,需要备份pos的下一个结点,先让newNode指向第二个结点再让pos指向newNode
> 
> 
> 



//指定位置后插入
void SLTInsertAfter(SLTNode *pos, int x)
{
assert(pos);
SLTNode *next = pos->next;
SLTNode *newNode = BuySLTNode(x);
pos->next = newNode;
newNode->next = next;
}


### 指定位置前插入


![在这里插入图片描述](https://img-blog.csdnimg.cn/4a6bbe415f5541caa166e0a408680954.gif#pic_center)



> 
> 1、在指定pos的前面插入,如果pos和ps在同一个位置就是头插了  
>  2、如果pos出现在链表的中间某个位置,要想在pos前插入一个新的结点就必须要找到pos前的一个结点prev,让这个结点prev指向新的结点newNode,最后让newNode指向当前结点
> 
> 
> 



//指定位置前插入
void SLTInsertBefor(SLTNode **ps, SLTNode *pos, int x)
{
assert(pos);
SLTNode *newNode = BuySLTNode(x);
if (pos == *ps)
{
newNode->next = *ps;
*ps = newNode;
}
else
{
SLTNode *cur = *ps;
SLTNode *prev = NULL;

	while (cur != pos) 
	{
		prev = cur;
		cur = cur->next;
	}
	prev->next = newNode;
	newNode->next = cur;
}

}


### 指定位置后删除


![在这里插入图片描述](https://img-blog.csdnimg.cn/bf026637f5f0477ba687d95b8cf2036a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> next用来保存pos位置的下一个结点,pos指向next的下一个结点,释放next位置的结点
> 
> 
> 



//移除指定位置之后
void SLTEraseAfter(SLTNode *pos)
{
//表为空不做处理
if(pos == NULL)
{
return ;
}
assert(pos);
SLTNode *next = pos->next;
pos->next = next->next;
free(next);
next = NULL;
}


### 移除指定位置



> 
> prev和cur一起一后,当cur与pos相遇了,就将prev链接cur的下一个结点,释放pos位置的结点,将指针置空
> 
> 
> 


![在这里插入图片描述](https://img-blog.csdnimg.cn/b2b3de24db174b2b82ac23e6cd419c35.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> 如果plist和pos指向一起,就是头删操作了
> 
> 
> 


![在这里插入图片描述](https://img-blog.csdnimg.cn/7f4f8c88e0624eb9b047d55994f3ccab.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



//移除指定位置
void SLTEraseBefor(SLTNode ** ps, SLTNode *pos)
{
assert(pos);
SLTNode *next = pos->next;
//pos等于ps,头删
if (*ps == pos)
{
free(*ps);
*ps = NULL;
*ps = next;
}
else
{
SLTNode *prev = NULL;
SLTNode *cur = *ps;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = cur->next;
free(cur);
cur = NULL;
}
}


## 力扣题


### 移除链表元素:


[点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/196e91a8b20345b5b3f4f6d702a9d2f8.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)  
 **考虑两种场景**


* 1、如果表的第一个结点的值就是val,那么就是头删了,释放第一个结点,需要将head的指向改变,指向下一个结点
* 2、如果表的所有结点全是val的情况,head的指向就可以一直改变,直到指向NULL,最后返回去的就是NULL



> 
> 链表移除结点的变形题,把特殊场景处理就能搞定
> 
> 
> 



struct ListNode* removeElements(struct ListNode* head, int val){

struct ListNode \*prev = NULL;
struct ListNode \*cur = head;
while(cur != NULL)
{
	//值为val
    struct ListNode \*del = NULL;
    if(cur->val != val)
    {
        prev = cur;
        cur = cur->next;
    }
    //值不为val
    else
    {
        //如果cur是头的情况
        struct ListNode \*next = cur->next;
        if(prev == NULL)
        {
            free(cur);
            head = next;
            cur = next;
        }
        //cur不是头
        else
        {
            prev->next = next;
            free(cur);
            cur = next;
        }
    }
}
return head;

}


第二种写法:带哨兵位的头节点,可以让prev指向哨兵位结点,这样就不需要考虑prev是否会存在空指针的问题了,同样的prev和cur一起一后,找到了值位val的结点,就释放该节点,cur继续指向下一个位置,最后只需要返回哨兵位结点的下一个位置



struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
guard->next = head;

struct ListNode \*prev = guard;
struct ListNode \*cur = head;
while(cur != NULL)
{
    if(cur->val != val)
    {
        prev = cur;
        cur = cur->next;
    }
    else
    {
        
        struct ListNode \*next = cur->next;
       
        prev->next = next;
        free(cur);
        cur = next;
    }
}
return guard->next;

}


![在这里插入图片描述](https://img-blog.csdnimg.cn/ecff38b93ee5427a80417442f5c2569a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)


### 206. 反转链表:


[点我](https://bbs.csdn.net/topics/618668825).  
 **实现思路**



> 
> 使用三个指针迭代的方法,prev和cur用来逆置结点的指向,next保证cur能找到下一个结点的位置,直到cur指向空了,循环停止,返回prev指针,整个链表也就逆置了
> 
> 
> 



struct ListNode* reverseList(struct ListNode* head){
if(head == NULL)
{
return NULL;
}

struct ListNode\* cur = head;
struct ListNode\* prev = NULL;
struct ListNode\* next = cur->next;

while(cur)
{
   //逆置
   cur->next = prev;
   //迭代
   prev = cur;
   cur = next;
   if(next != NULL)
   next = next->next;
}

return prev;

}



> 
> 思路二:必做,链表头插的变型题,将原链表遍历一遍,取原链表的结点头插到新的表中
> 
> 
> 



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;

}


### 876. 链表的中间结点:


[点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/741ac587e9b3439ca375015644ee3f2a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> 快慢指针解法,快指针走两步慢指针走一步,当快指针走到链表NULL位置的时候,或者快指针走到最后一个结点的位置,循环终止,返回慢指针
> 
> 
> 



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

    fast = fast->next->next;
   
}

return slow;

}


### 链表中倒数第k个结点:


[点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/48b10f82084f4e47842d18909c815e6b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> 快指针先走k步,快指针走完k步后,快指针和慢指针一起走,当快指针走完了,slow就是倒数第k个结点,就返回slow的位置
> 
> 
> 极端情况:如果fast先走k步,k大于链表的长度,链表可能存在空表,是空表就返回NULL
> 
> 
> 



struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
// write code here
struct ListNode* fast = pListHead;
struct ListNode* slow = pListHead;

while(k--)
{
    //k大于链表长度,fast已经走到NULL了,
    if(fast == NULL)
        return NULL;
    fast = fast->next;
}

while(fast)
{
   fast = fast->next;
   slow = slow->next;
}
return slow;

}


### 21. 合并两个有序链表


链接: [点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e73bbe6ebd6a48d28d0af1c6f336f369.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> 思路:合并两个链表只需要将原链表中最小的值尾插到新链表中去
> 
> 
> 



struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if(l1 == NULL)
return l2;
if(l2 == NULL)
return l1;
if(l1 == NULL && l2 == NULL)
return NULL;

struct ListNode\* newList = NULL;
struct ListNode \*tail = newList;
//取下最小值做新链表的头
if(l1->val < l2->val)
{
    newList = tail = l1;
    l1 = l1->next;
}
else
{
    newList = tail = l2;
    l2 = l2->next;
}
//取两个链表中最小值尾插到新的链表中去
while(l1 && l2)
{
   if(l1->val < l2->val)
   {
       tail->next = l1;
       l1 = l1->next;
   }
   else
   {
       tail->next = l2;
       l2 = l2->next;
   }
   tail = tail->next;
}

//如果有一个链表还没遍历完就继续尾插到新链表去
if(l1)
{
    tail->next = l1;
}
if(l2)
{
    tail->next = l2;
}

return newList;

}



> 
> 带哨兵位的头节点不需要考虑新链表头尾都是是NULL的这种情况
> 
> 
> 



struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
//创建哨兵头节点
struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* tail = head;
tail->next = NULL;

while(l1 && l2)
{
    if(l1->val < l2->val)
    {
        tail->next = l1;
        l1 = l1->next;
    }
    else
    {
        tail->next = l2;
        l2 = l2->next;
    }
    tail = tail->next;
}

//还剩的
if(l1){
    tail->next = l1;
}
if(l2){
    tail->next = l2;
}

//释放动态开辟的结点,返回新的头
struct ListNode\* node = head;
head = head->next;
free(node);
return head;

}


### OR36 链表的回文结构


链接: [点我](https://bbs.csdn.net/topics/618668825) .  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f4963ab123324c4a88500243825bc845.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> 解题思路:先找出中间结点(快慢指针法),将中间结点起始位置往后整体逆置,返回逆置后的头指针,得到后部分逆置的链表,再跟原链比较
> 
> 
> 



class PalindromeList {
public:
struct ListNode* middleNode(struct ListNode* head){
if(head == NULL)
{
return NULL;
}
struct ListNode* fast = head;
struct ListNode* slow = head;
while(fast && fast->next)
{
slow = slow->next;

    fast = fast->next->next;
   
}

return slow;

}
struct ListNode* reverseList(struct ListNode* head){
if(head == NULL)
{
return NULL;
}

struct ListNode\* cur = head;
struct ListNode\* prev = NULL;
struct ListNode\* next = cur->next;

while(cur)
{
   //逆置
   cur->next = prev;
   //迭代
   prev = cur;
   cur = next;
   if(next != NULL)
   next = next->next;
}

return prev;

}
bool chkPalindrome(ListNode* A) {
// write code here
//找到中间结点整体逆置,最后比较
struct ListNode* mid = middleNode(A);
struct ListNode* rhead = reverseList(mid);

    //比较
    while(A && rhead)
    {
        if(A->val != rhead->val)
        {
            return false;
        }
        else
        {
            A = A->next;
            rhead = rhead->next;
        }
    }
    return true;
}

};


![在这里插入图片描述](https://img-blog.csdnimg.cn/b8e9fdb259b544dca97dfb90e3d02611.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)  
 160. 相交链表  
 链接: [点我](https://bbs.csdn.net/topics/618668825).



> 
> 链表的相交并不是直线的相交,而是两个链表中存在一个公共结点,这样的链表我们可以称它是相交链表,比较结点的地址,如果相同那么就是相交的,否则不是,让长距离的先走差距步,最后再同时走,如果中间相交就返回该结点,否则返回NULL
> 
> 
> 



struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
//记录链表的长度
int lenA = 0,lenB = 0;
struct ListNode *curA = headA;
struct ListNode *curB = headB;
while(curA->next)
{
lenA++;
curA = curA->next;
}
while(curB->next)
{
lenB++;
curB = curB->next;
}
//如果不相遇那么链表的最后一个结点一定不同
if(curA != curB)
return NULL;
//定义长的链表,定义短的链表
struct ListNode * longlist = headA, *shortlist = headB;
int gap = abs(lenB - lenA);
if(lenA < lenB)
{
longlist = headB;
shortlist = headA;
}
//长链表先走gap步
while(gap–)
{
longlist = longlist->next;
}
//最后一起走
while(longlist != shortlist)
{
longlist = longlist->next;
shortlist = shortlist->next;
}

return longlist;

}


### 141. 环形链表


链接: [点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ab93b169a750485fbf1ca357879d21e8.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> 快慢指针解法,快指针走两步,慢指针走一步,当他们相遇了,就能证明链表是环形链表,如果fast走到NULL的位置或者fast的下一个结点是空了,那么链表就不为环形
> 
> 
> 



bool hasCycle(struct ListNode *head) {
struct ListNode * fast = head;
struct ListNode * slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
return true;
}
}
return false;
}


延申问题


* 1、为什么slow走一步,fast走两步,它们一定会在环里面相遇,会不会永远追不上,请证明
* 2、slow走一步,fast走3步?走4步?走n步行不行?请证明!
* 3、求环的入口点


![在这里插入图片描述](https://img-blog.csdnimg.cn/98c37915789e4b3aad5ada9a4acb3024.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)  
 不会,假设slow进环的时候fast跟slow的差距是N, 紧接着追击的过程,fast往前走2步,slow走1步,它们每次一走,它们之间的距离缩小1,N-1 N-2 … 2 1 0,直到等于0的时候就相遇了


**2、slow走一步,fast走3步?走4步?走n步行不行?请证明!**  
 假设slow进环的时候fast跟slow的差距是N, 紧接着追击的过程,fast往前走3步,slow走1步,它们每次一走,它们之间的距离缩小2,会分两种情况,如果是奇数个,如果是偶数个呢?如果是偶数个可以相遇,如果是奇数(-1)个并不会相遇,假设环的大小是C,那么slow和falst的差距就是C-1了,如果C-1恰好是奇数就永远追不上  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/52a523b8f872437dbf939504a98f12a6.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_14,color_FFFFFF,t_70,g_se,x_16)  
 总结:如果slow进环时,slow跟fast的差距是奇数,且环的长度是偶数,那么它们两个再环里面就会一直打圈



> 
> 解题思路:  
>  将fast和slow的相遇点找出来,meet表示相遇点,从相遇点meet开始  
>  head走一步meet走一步,如果他们相遇了,那么这就是入口点
> 
> 
> 




![img](https://img-blog.csdnimg.cn/img_convert/6d078981e23364724b3b62149920cfa2.png)
![img](https://img-blog.csdnimg.cn/img_convert/e70b98993399240e7259307816585970.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**


**2、slow走一步,fast走3步?走4步?走n步行不行?请证明!**  
 假设slow进环的时候fast跟slow的差距是N, 紧接着追击的过程,fast往前走3步,slow走1步,它们每次一走,它们之间的距离缩小2,会分两种情况,如果是奇数个,如果是偶数个呢?如果是偶数个可以相遇,如果是奇数(-1)个并不会相遇,假设环的大小是C,那么slow和falst的差距就是C-1了,如果C-1恰好是奇数就永远追不上  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/52a523b8f872437dbf939504a98f12a6.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_14,color_FFFFFF,t_70,g_se,x_16)  
 总结:如果slow进环时,slow跟fast的差距是奇数,且环的长度是偶数,那么它们两个再环里面就会一直打圈



> 
> 解题思路:  
>  将fast和slow的相遇点找出来,meet表示相遇点,从相遇点meet开始  
>  head走一步meet走一步,如果他们相遇了,那么这就是入口点
> 
> 
> 




[外链图片转存中...(img-dHRBrVVC-1715561511023)]
[外链图片转存中...(img-k8WTF82j-1715561511024)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

请问您需要的是两个数组的交集元素还是交集元素的数量? 如果是交集元素,可以采用双指针的方式,先将两个数组排序,然后设定两个指针 i 和 j,分别指向两个数组的开头,比较两个指针所指向的元素的大小,如果相等,则说明找到了一个交集元素,将其存到结果数组中;如果不相等,则将指向小的元素的指针向后移动一位,直到其中一个指针越界为止。 代码实现如下: ```c int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){ int i = 0, j = 0, k = 0; int* res = (int*)malloc(sizeof(int) * (nums1Size > nums2Size ? nums2Size : nums1Size)); // 排序 qsort(nums1, nums1Size, sizeof(int), cmp); qsort(nums2, nums2Size, sizeof(int), cmp); while (i < nums1Size && j < nums2Size) { if (nums1[i] == nums2[j]) { res[k++] = nums1[i]; i++; j++; } else if (nums1[i] < nums2[j]) { i++; } else { j++; } } *returnSize = k; return res; } int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; } ``` 如果是交集元素的数量,可以采用哈希表的方式,用一个哈希表来记录第一个数组中的元素出现的次数,然后遍历第二个数组,在哈希表中查找是否存在相同的元素,如果存在,则说明找到了一个交集元素,将其计数并从哈希表中删除该元素,最后返回计数结果即可。 代码实现如下: ```c int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){ int i = 0, j = 0, k = 0; int* res = (int*)malloc(sizeof(int) * (nums1Size > nums2Size ? nums2Size : nums1Size)); int* hash = (int*)malloc(sizeof(int) * 1001); // 由于目条件限制在 [0, 1000] 范围内,所以哈希表可以开得比较小 memset(hash, 0, sizeof(hash)); for (i = 0; i < nums1Size; i++) { hash[nums1[i]]++; } for (j = 0; j < nums2Size; j++) { if (hash[nums2[j]] > 0) { res[k++] = nums2[j]; hash[nums2[j]]--; } } *returnSize = k; return res; } ``` 希望这些代码能够帮到您,如有疑问请随时问我~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值