数据结构-线性表
来源:互联网 发布:暗黑破坏神2画面优化 编辑:程序博客网 时间:2024/06/14 09:07
算法题主要来自剑指offer上面的题目,本章主要是重新复习下线性表及其相关的算法题。
二维数组中的查找
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution {public: bool Find(vector<vector<int> > array,int target) { bool isFind = false; if (array.size() == 0) { return isFind; } int currentRow = 0; int currentColumn = array[0].size() - 1; while (currentRow <= array.size()-1 && currentColumn >= 0) { vector<int> rowVector = array[currentRow]; if (rowVector[currentColumn] > target) { currentColumn--; }else if (rowVector[currentColumn] < target){ currentRow++; }else{ // 相等,说明找到 isFind = true; return isFind; } } return isFind; }};
从尾到头打印链表
输入一个链表,从尾到头打印链表每个节点的值。
输入描述
输入为链表的表头
输出描述
输出为需要打印的“新链表”的表头
/*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) :* val(x), next(NULL) {* }* };*/class Solution {public: vector<int> printListFromTailToHead(struct ListNode* head) { stack<int> stack; vector<int> result; ListNode *pNode = head; if (pNode == NULL) { return result; } while (pNode!= NULL) { stack.push(pNode->val); pNode = pNode->next; } while (!stack.empty()) { result.push_back(stack.top()); stack.pop(); } return result; }};
链表中环的入口结点
一个链表包含环,请找出该链表的环的入口结点
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public:/** * 找出两个快慢结点相遇的结点 * * @param pHead <#pHead description#> * * @return <#return value description#> */ListNode* meetNode(ListNode* pHead){ // 慢结点,每次移动1步 ListNode *pSlowNode = pHead; // 快结点,每次移动2步 ListNode *pFastNode = pHead->next; if (pHead == NULL) { return NULL; } if (pHead->next == NULL) { return NULL; } while (pSlowNode != pFastNode) { pSlowNode = pSlowNode->next; pFastNode = pFastNode->next->next; } return pSlowNode;}/** * 求出头结点到相遇结点的距离 * * @param pHead <#pHead description#> * @param pMeetNode <#pMeetNode description#> * * @return <#return value description#> */int distanceFormHeadToMeetNode(ListNode* pHead,ListNode* pMeetNode){ int distance = 0; ListNode* pNode = pHead; while (pNode != pMeetNode) { distance++; pNode = pNode->next; } return distance;}ListNode* EntryNodeOfLoop(ListNode* pHead){ if (pHead == NULL) { return NULL; } if (pHead->next == NULL) { return NULL; } ListNode* pNode1 = pHead; ListNode* pNode2 = pHead->next; ListNode* pMeetNode = meetNode(pHead); int distance = distanceFormHeadToMeetNode(pHead, pMeetNode); // pHead2先移动distance个距离 while (distance != 0) { pNode2 = pNode2->next; distance--; } while (pNode1 != pNode2) { pNode1 = pNode1->next; pNode2 = pNode2->next; } return pNode1;}};
反转链表
输入一个链表,反转链表后,输出链表的所有元素。
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* ReverseList(ListNode* pHead) { ListNode* pReversedHead = NULL; ListNode* pNode = pHead; ListNode* pPrev = NULL; while (pNode != NULL) { ListNode* pNext = pNode->next; if (pNext == NULL) { pReversedHead = pNode; } pNode->next = pPrev; pPrev = pNode; pNode = pNext; } return pReversedHead; }};
链表中倒数第k个结点
输入一个链表,输出该链表中倒数第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) { // 先求出链表长度length,倒数第k个结点相当于第 length - k + 1个结点 ListNode* pNode = pListHead; if (pListHead == NULL) { return NULL; } int length = 1; while (pNode != NULL) { length++; pNode = pNode->next; } pNode = pListHead; ListNode *pFindNode = NULL; // 取得了链表的长度length后,找到第 length - k + 1 int count = 1; while (pNode != NULL) { count++; if (count == length - k + 1) { pFindNode = pNode; break; } pNode = pNode->next; } return pFindNode; }};
只需遍历一次的算法(使用两个指针)(注意代码的鲁棒性)
/*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 (pListHead == NULL || k== 0) { return NULL; } ListNode* pAheadNode = pListHead; ListNode* pBehind = pListHead; for (int i = 0; i < k-1; i++) { // pAheadNode向前移动 if (pAheadNode->next != NULL) { pAheadNode = pAheadNode->next; }else{ return NULL; } } while (pAheadNode->next != NULL) { pBehind = pBehind->next; pAheadNode = pAheadNode->next; } return pBehind; }};
合并两个排序的链表(注意采用递归的思想)
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
不用递归的思想
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { ListNode* pHead = NULL; ListNode* pLast = NULL; if (pHead1 == NULL && pHead2 == NULL) { return NULL; }else if (pHead1 == NULL && pHead2 != NULL){ return pHead2; }else if (pHead1 != NULL && pHead2 == NULL){ return pHead1; }else{ ListNode* pNode1 = pHead1; ListNode* pNode2 = pHead2; // 先找出链表的头结点 if (pNode1->val <= pNode2->val) { pHead = pNode1; pNode1 = pNode1->next; }else{ pHead = pNode2; pNode2 = pNode2->next; } pLast = pHead; while (pNode1 != NULL || pNode2 != NULL) { ListNode* pNode = NULL; if (pNode1 == NULL) { pLast->next = pNode2; return pHead; } if (pNode2 == NULL) { pLast->next = pNode1; return pHead; } if (pNode1->val <= pNode2->val) { pNode = pNode1; pNode1 = pNode1->next; }else{ pNode = pNode2; pNode2 = pNode2->next; } // 找到最小的结点后,最后一个结点指向该结点 pLast->next = pNode; pLast = pNode; } } return pHead; }};
使用递归的思想
/*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* pHead = NULL; if (pHead1->val < pHead2->val) { pHead = pHead1; pHead->next = Merge(pHead1->next, pHead2); }else{ pHead = pHead2; pHead->next = Merge(pHead1, pHead2->next); } return pHead; }};
复杂链表的复制
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
/*struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : label(x), next(NULL), random(NULL) { }};*/class Solution {public:RandomListNode* Clone(RandomListNode* pHead) { if(!pHead) return NULL; RandomListNode *currNode = pHead; while(currNode){ RandomListNode *node = new RandomListNode(currNode->label); node->next = currNode->next; currNode->next = node; currNode = node->next; } currNode = pHead; while(currNode){ RandomListNode *node = currNode->next; if(currNode->random){ node->random = currNode->random->next; } currNode = node->next; } //拆分 RandomListNode *pCloneHead = pHead->next; RandomListNode *tmp; currNode = pHead; while(currNode->next){ tmp = currNode->next; currNode->next =tmp->next; currNode = tmp; } return pCloneHead; }};
两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/class Solution {public: ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) { if (pHead1 == NULL || pHead2 == NULL) { return NULL; } // 分别计算两个链表的长度 int length1 = 1; int length2 = 1; ListNode* pNode1 = pHead1; ListNode* pNode2 = pHead2; while (pNode1->next != NULL) { length1++; pNode1 = pNode1->next; } while (pNode2->next != NULL) { length2++; pNode2 = pNode2->next; } // 比较两个链表的长度 int distance = length1 - length2; if (distance > 0) { // 说明链表1的长度长,链表1先走distance步。 while (distance > 0) { pHead1 = pHead1->next; distance--; } }else{ // 链表2的长度长 distance = -distance; while (distance > 0) { pHead2 = pHead2->next; distance--; } } ListNode* commonNode = NULL; // 此时两个链表走的长度是相同的,可以同时遍历 while (pHead1 != pHead2 && pHead1 != NULL && pHead2 != NULL) { pHead1 = pHead1->next; pHead2 = pHead2->next; } commonNode = pHead1; return commonNode; }};
删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
/*struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { }};*/// 递归class Solution {public: ListNode* deleteDuplication(ListNode* pHead) { if (pHead==NULL) return NULL; if (pHead!=NULL && pHead->next==NULL) return pHead; ListNode* current; if ( pHead->next->val==pHead->val){ current=pHead->next->next; while (current != NULL && current->val==pHead->val) current=current->next; return deleteDuplication(current); } else { current=pHead->next; pHead->next=deleteDuplication(current); return pHead; } }};
旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
- 数据结构拾遗---线性表
- 整理--数据结构--线性表
- 数据结构(线性表)
- 整理--数据结构--线性表
- 数据结构--顺序线性表
- 数据结构之线性表
- 数据结构-线性链表
- 数据结构-线性表
- 复习 [数据结构] ---- 线性表
- 数据结构---线性表
- 数据结构复习-线性表
- 数据结构之线性表
- 数据结构之线性表
- 线性链表---数据结构
- 数据结构—线性表
- 数据结构 线性表
- 数据结构----线性表
- 数据结构之线性表
- SpringMVC之HelloWorld
- 找出字符串
- BZOJ 4569: [Scoi2016]萌萌哒【倍增并查集
- Medical image registration(section7)
- HSDIS:JIT生成代码反汇编
- 数据结构-线性表
- boost-pretty-printer配置及问题
- 为了梦想,努力奋斗! 追求卓越,成功就会在不经意间追上你 mysql之触发器trigger
- 利用SharePoint 2013 创建Service Desk 网站之分配一线工程师支持!
- AbstractSet抽象类源码解析
- 电池极片检测项目总结
- Java中的equals和==
- Linux的众多版本
- hive文件存储格式