一些数据结构经典习题
part 2
链表

1.给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* prev=NULL;struct ListNode* cur=head;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;
}


此题是对链表删除功能的一个应用,要考虑到特殊情况头删。

做法二

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
struct ListNode
{int val;struct ListNode* next;
};struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* tail = NULL;struct ListNode* cur = head;//哨兵位head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));tail->next = NULL;//防止野指针while (cur){if (cur->val == val){struct ListNode* del = cur;cur = cur->next;free(del);}else{tail->next = cur;tail = tail->next;cur = cur->next;}}tail->next = NULL;struct ListNode* del = head;head = head->next;free(del);return head;
}int main()
{struct ListNode* n1 = (struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2 = (struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3 = (struct ListNode*)malloc(sizeof(struct ListNode));assert(n3);struct ListNode* n4 = (struct ListNode*)malloc(sizeof(struct ListNode));assert(n4);n1->val = 7;n2->val = 7;n3->val = 8;n4->val = 7;n1->next = n2;n2->next = n3;n3->next = n4;n4->next = NULL;struct ListNode* head = removeElements(n1, 7);return 0;
}

反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表

方法一:头插法

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;
}

方法二:改变指向

struct ListNode* reverseList(struct ListNode* head)
{if(head==NULL)//防止n2->next出现野指针return NULL;struct ListNode *n1,*n2,*n3;n1=NULL;n2=head;n3=n2->next;while(n2){//改指向n2->next=n1;//迭代,改值n1=n2;n2=n3;//判断是否结束if(n3)n3=n3->next;}return n1;
}

链表的中间的结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

struct ListNode* middleNode(struct ListNode* head)
{struct ListNode * slow,*fast;//*不要掉了fast=slow=head;//顺序不能变while(fast&&fast->next){slow=slow->next;fast=fast->next->next;//一次走两格}return slow;
}

分两种情况,奇数个和偶数个

链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k )
{struct ListNode *fast,*slow;slow=fast=pListHead;//fast提前走k步while(k--){//防止还没走到k步,链表就结束了if(fast==NULL)return NULL;fast=fast->next;}while(fast){fast=fast->next;slow=slow->next;}return slow;
}

此题使用双指针,快慢指针,注意链表长度和k的关系

合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

解法一:
不带哨兵位头结点

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


首先判断两个链表是否为空,为空返回另外一个链表
不为空则进入循环,从头判断链表的值大小,其中要判断尾指针是否为空,为空相当于头插链表。
最后,当一个链表为空,直接将另一个链表剩余值返回到尾指针。

带哨兵位头结点解法

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{struct ListNode* head,*tail;head=tail=(struct ListNode*)malloc(sizeof(struct ListNode));tail->next=NULL;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* list=head->next;free(head);return list;
}

链表分割

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

此题使用了哨兵位头结点

class Partition {public:ListNode* partition(ListNode* pHead, int x){struct ListNode* lesshead,*lesstail,*greaterhead,*greatertail;lesshead=lesstail=(struct ListNode*)malloc(sizeof(struct ListNode));greaterhead=greatertail=(struct ListNode*)malloc(sizeof(struct ListNode));lesstail->next=NULL;greatertail->next=NULL;struct ListNode* cur=pHead;while(cur){if(cur->val<x){lesstail->next=cur;lesstail=lesstail->next;}else{greatertail->next=cur;greatertail=greatertail->next;}cur=cur->next;}lesstail->next=greaterhead->next;greatertail->next=NULL;struct ListNode* list=lesshead->next;free(lesshead);free(greaterhead);return list;}
}

链表的回文结构

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

struct ListNode* middleNode(ListNode* head)
{struct ListNode * fast,*slow;slow=fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;}return slow;
}
struct ListNode* reverseList(ListNode* head)
{if(head==NULL)return NULL;struct ListNode *n1,*n2,*n3;n1=NULL:n2=head;n3=n2->next;while(n2){n2->next=n1;n1=n2;n2=n3;if(n3)n3=n3->next;}return n1;
}class PalindromeList {public:bool chkPalindrome(ListNode* A){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;}};

此题思路是:先找到中间结点,再将后半部分反转,前部分和后半部分进行比较,相同返回true,不同返回false.

相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{struct ListNode* curA=headA,*curB=headB;int lenA=1,lenB=1;while(curA->next){curA=curA->next;lenA++;}while(curB->next){curB=curB->next;lenB++;}if(curA!=curB){return NULL;}else{struct ListNode* longlist=headA,*shortlist=headB;if(lenA<lenB){longlist=headB;shortlist=headA;}int gap=abs(lenA-lenB);while(gap--){longlist=longlist->next;}while(shortlist!=longlist){shortlist=shortlist->next;longlist=longlist->next;}return shortlist;}
}

基本思路是:先求出两个链表的长度,同时如果两个链表不相等则说明不相交,返回NULL。让长的链表先走差距步,当长链表等于断链表时,返回短链表此时就是相交结点。

数据结构经典习题【part2】相关推荐

  1. 数据结构经典习题【part 1】

    学习数据结构遇到的一些经典习题 part 1 顺序表习题 消失的数字 数组nums包含从0到n的所有整数,但其中缺了一个.请编写代码找出那个缺失的整数.你有办法在O(n)时间内完成吗? 思路一: 1. ...

  2. 已知长短轴求椭圆上任意一点的坐标_高中数学必修2:平面解析几何——椭圆(经典习题)...

    今天接着给大家分享关于高中数学必修2平面解析几何中椭圆知识点讲解,从三个方面进行讲解:基础梳理.要点整理.经典高考习题解题过程及答案. 一.基础梳理 1.椭圆的定义 2.椭圆的标准方程和几何性质 要点 ...

  3. 数据结构经典算法集锦

    数据结构经典算法集锦 第2章 线性表 KMP算法 //获得next数组 void GetNext(char *t, int next[MAX]) {int i = 1, j = 0;next[1] = ...

  4. 新颖的c语言题目,新颖版c语言经典习题100例(全面面)

    新颖版c语言经典习题100例(全面面) (66页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 实用文档C语言习题100例(最新整理版) ...

  5. c语言全面,最新版c语言经典习题100例(最全面).doc

    最新版c语言经典习题100例(最全面).doc C语言习题100例(最新整理版) 习题目录:(按住Ctrl点击可以快速跳转到对应页面) TOC \o "1-3" \h \z \u ...

  6. 算法竞赛入门经典 习题3-2 分子量 Molar Mass

    给出一种物质的分子式(不带括号),求其分子量.本题分子式中只包含四种原子,分别为C.H.O.N,原子量分别为12.01,1.008,16.00,14.01.例如,C6H5OH的分子量为94.108g/ ...

  7. oracle经典习题(一)

    oracle经典习题(一) 1.显示与BLAKE在同一部门工作的雇员的姓名.工作和入职日期,但是BLAKE不包含在内 1.1 示例sql语句 SELECT ename,job,hiredate FRO ...

  8. oralce 经典习题系列-查询

    oralce 经典习题系列 数据库数据类型 The problem 1在已经创建的employee表中进行如下操作: (1)计算所有女员工('F')的工龄. (2)使用ROWNUM查询从第3条记录开始 ...

  9. 韩信点兵(hanxin)--算法竞赛经典习题2-2:相传韩信才智过人,从不清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,他每次只要掠一眼队伍的排尾就知道总数(C++实现)

    韩信点兵(hanxin)–算法竞赛经典习题2-2:相传韩信才智过人,从不清点自己军队的人数,只要让士兵先后以三人一排.五人一排.七人一排地变换队形,他每次只要掠一眼队伍的排尾就知道总数. (C++实现 ...

最新文章

  1. ftp服务器压缩文件,ftp压缩服务器文件
  2. sql服务找不到服务器,我找不到SQL服务管理器
  3. 设计模式C++实现(4)——桥接模式
  4. 【C++学习笔记四】运算符重载
  5. python 伪造源ip_Swaks伪造邮件
  6. 实时查看磁盘inode和block变化
  7. 怎么提升企业数据分析能力
  8. ubuntu修改文件权限
  9. postgresql搭建从库
  10. Node.js 应用开发详解07 CPU 过载保护设计:如何在服务层面确保系统稳定?
  11. c语言程序乔奎,迂回
  12. win10进程太多怎么优化_教你优化Windows7后台进程,让你的电脑启动更快、运行更流畅...
  13. mysql 1055 - Expression 解决
  14. UE4中三维几何总结——几何学基础
  15. 全球的MLOps和ML工具概览
  16. 单片机ADC0832电压检测程序(充电自动提醒)
  17. 5个借势小技巧,教你打造中秋爆款营销活动
  18. 人生的两个方向:一个是出门,一个是回家(转载)
  19. Android 新建一个APP进程的源代码分析(ActivityManageService->Zygote->ActivityThread)
  20. 前端解决表情符号乱码问题(前端处理表情符号编码)@令狐张豪

热门文章

  1. postgres 源码解析9 CLOG管理器--1
  2. 解决org.json.JSONException: A JSONObject text must begin with '{' at character 1 of {
  3. 为什么要“亲职教育”
  4. 企业行业培训讲座在线观看目录
  5. (软件工程)GPU并行软件开发指北
  6. 一种水下鱼类图像特征学习与目标识别框架
  7. 苹果MAC电脑怎么只装WIN7系统
  8. 2021年农历新年最后一个外业记录(POSMV和Reson7125)
  9. 4K分辨率搭配光学变焦功能,极米H6成旗舰家用投影首选
  10. 信号处理——基础知识及常用算法