算法学习记录十二(C++)--->链表题目集合
来源:互联网 发布:课程录播软件 编辑:程序博客网 时间:2024/05/22 00:08
题目一
输入一个链表,输出该链表中倒数第k个结点。
分析
最普通的方法就是,先统计单链表中节点的个数,然后再找到n-k个节点,时间复杂度为O(n)另一个思路就是双指针,,先让前面的指针走向正想第k个节点,这样前后两个节点的差距就是k-1,之后前面两个指针一起走,前面的指针走到最后一个节点的时候,后走的那个指针就是倒数第k个节点
代码
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(k==0 || pListHead == NULL){ // 这里k的计数是从1开始的,若k为0或链表为空返回NULL return NULL; } ListNode *pHead = pListHead; ListNode *pBehind = pListHead; while(k>1 && pHead != NULL){ // 前面的指针先走到正向第k个结点 pHead = pHead->next; k--; } if(k>1||pHead==NULL){ // 结点个数小于k,返回NULL return NULL; } while(pHead->next!=NULL){// 前后两个指针一起向前走,直到前面的指针指向最后一个结点 pHead=pHead->next; pBehind=pBehind->next; } return pBehind; // 后面那个指针所指节点就是倒数第k个 }};
题目二
输入一个链表,反转链表后,输出链表的所有元素
分析
1.非递归 三指针 pPrev -> pNode -> pNext; 我们先保存原来的下一个指针位置,要不然翻转后其next会指向pPrev,从而丢失指向pNext的指针 接着反转指针, 然后下面指针同步后移,以便处理后面的指针2.递归核心代码,当前节点的两次next取值指向自己,就是翻转pHead->next->next=pHead;pHead->next=NULL;
代码 非递归
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*//*next = head.next;//首先记录当前节点的下一个节点,(保存起来)head.next = pre;//让当前节点指向前一个节点,因为要反序嘛pre = head;//让前一个节点值,取代当前的节点值。因为要继续向下走head = next;//让下一个节点,取代当前节点。同样是向下走,为下一次循环做准备*//*class Solution {public: ListNode* ReverseList(ListNode* pHead) { ListNode *pNode = pHead; ListNode *pPre = NULL; ListNode *pNext = NULL; while(pNode != NULL){ pNext = pNode->next; pNode->next = pPre; pPre = pNode; pNode = pNext; } return pPre; }};*/
代码 递归
class Solution {public: // 这个递归非常赞 举个例子 // 例如 1->2->3-NULL 这个链表 // 当pHead为1的时候传进去 内部会调用ReverseList(2)继续传递,而且每次调用都会触发一下两行代码 // pHead->next->next=pHead;pHead->next=NULL; // 当你调用ReverseList(3)的时候就直接返回3这个节点,不调用那两行代码,然后进行回归 // pHead->next->next=pHead; 这句话的意思是,例如节点2调用的时候,pHead是2,递归最后一层ReverseList(3)返回3 // 然后->next就是对应的3节点,再next就是反序替换节点 两个next指向当前节点,就是反转一次了 // pHead->next=NULL;这句话的意思就是最后一个节点的next为Null结束 ListNode* ReverseList(ListNode* pHead) { //如果链表为空或者链表中只有一个元素 if(pHead==NULL||pHead->next==NULL) return pHead; //先反转后面的链表,走到链表的末端结点 ListNode* pReverseNode=ReverseList(pHead->next); //再将当前节点设置为后面节点的后续节点 pHead->next->next=pHead; pHead->next=NULL; return pReverseNode; }};
题目三
已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
分析
这个类似归并排序。尤其注意两个链表都为空,和其中一个为空时的情况。只需要O(1)的空间。时间复杂度为O(max(len1, len2))。分别用递归和常规指针进行操作
常规操作
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*//*class Solution {public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { if(pHead1 == NULL){ return pHead2; } if(pHead2 == NULL){ return pHead1; } ListNode *orginalHeader = NULL; ListNode *currentNode = NULL; while(pHead1 && pHead2){ if(pHead1->val < pHead2->val){ if(orginalHeader == NULL){ // 该判断为了找出对应的头结点保存到orginalHeader orginalHeader = currentNode = pHead1; } else{ currentNode->next = pHead1; // 取下链表的当前节点放到临时链表的next节点 currentNode = currentNode->next; // 临时节点往后移动一位 } pHead1 = pHead1->next; // 每次比较之后都要把比较小的链表往后移动一个 } else{ if(orginalHeader == NULL){ orginalHeader = currentNode = pHead2; } else{ currentNode->next = pHead2; currentNode = currentNode->next; } pHead2 = pHead2->next; } } // 一个为空的时候结束遍历而且直接拼接到后面 if(pHead1 == NULL){ currentNode->next = pHead2; } else{ currentNode->next = pHead1; } return orginalHeader; }};*/
递归拼接
class Solution {public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { if(pHead1 == NULL){ return pHead2; } if(pHead2 == NULL){ return pHead1; } ListNode *tempNode = NULL; if(pHead1->val < pHead2->val){ pHead1->next = Merge(pHead1->next,pHead2); return pHead1; // 一开始的头结点大小决定返回head1还是head2 }else{ pHead2->next = Merge(pHead1,pHead2->next); return pHead2; } }};
阅读全文
0 0
- 算法学习记录十二(C++)--->链表题目集合
- [记录] 算法学习集合
- STL学习记录(十二):非修改类算法
- 【数据结构与算法】链表题目集合
- scala学习笔记(十二) 集合
- java学习笔记(二十二)集合
- mysql 学习记录(十二)--触发器
- 无人机驾驶员培训学习记录(十二)
- 链表题目集合
- 算法学习记录三(C++)--->从尾到头打印链表每个节点的值
- 算法集合(C++)
- 算法精解十二(C语言版)
- 算法精解二十二(C语言版)
- c语言题目集合
- c语言题目集合
- c语言题目集合
- java学习笔记(十二)----集合
- C语言程序学习(十二)笔记
- 辉光管电子时钟DIY记录-动态扫描驱动方式
- 页面跳转和获取的知识
- QT的学习(1)
- 每天一个linux命令(57):ss命令
- 2363 Blocks
- 算法学习记录十二(C++)--->链表题目集合
- UE4学习笔记12th:配置输入以控制相机
- 分布式系统的正确性验证方法
- Java语言动态代理(Dynamic Proxies)实例
- Java 模板技术
- monkey测试基础命令
- 使用parted磁盘分区及挂载
- 二、ElasticSearch基本操作
- node Promise/Deffered原理解析