链表专题[三种逆置方式和微软笔试题]
来源:互联网 发布:网络系统集成设计方案 编辑:程序博客网 时间:2024/06/11 13:34
说起链表,是大家最熟悉的数据结构了,也是大学上课时比较先讲到的。那么是否真正掌握了呢。
单链表逆置是最常考的题目,但完全写正确好像三种方式也没那么容易吧。
第一种:非递归,思路就是从头结点开始,记录头结点的下一个结点,同时将头结点的指针指向之前的结点(设为NULL),然后将头结点的值赋给之前的结点,然后继续下一个结点的逆置,直到为空。
第二种: 递归方式。思路就是一直递归,直到最后一个结点的之前一个结点结束,这时然后最后一个结点的指针指向之前一个结点,同时将之前一个结点的指针置为空(这样顺便修改了原来链表头结点的指针为空)。难点在于怎么返回逆置之后的头结点。
第三种: 栈。既然可以递归了那么考虑用栈来解决。
好了,貌似单链表比较复杂的操作我们掌握了。问题解决了,那么是否能灵活运用呢?看下面一道题目(微软2014年校招编程题)
Given a singly linked list L: (L0 , L1 , L2...Ln-1 , Ln). Write a program to reorder it so that it becomes(L0 , Ln , L1 , Ln-1 , L2 , Ln-2...).
struct Node
{
int val_;
Node* next;
};
Notes:
1)Space Complexity should be O(1)
2)Only the ".next" field of a node is modifiable.
注意:空间复杂度为O(1)意味着不能有大于O(1)的辅助空间。
注意是从尾倒着插,可能会用到逆置,那解题思路是神马呢?
根据长度将链表分为两半,对后面的链表进行逆置,然后将两个链表合并(擦,神一样的思路啊,这就是链表逆置和合并的灵活应用了,当做为笔试题是否能想到呢。。。),好了,废话不多说了,代码在下面,看注释吧。
#include<iostream>#include<string>#include<stack>using namespace std;struct ListNode{int value;ListNode* next;};//增加元素void AddToList(ListNode** pHead,int value){ListNode* pTemp = *pHead; pTemp = (ListNode *)malloc(sizeof(ListNode));pTemp->value = value;pTemp->next = NULL;if(*pHead == NULL)*pHead = pTemp;else{ListNode* pNTemp = *pHead;while(pNTemp->next != NULL)pNTemp = pNTemp->next;pNTemp->next = pTemp;}}//求长度int ListLen(ListNode* pHead){int n =0;while(pHead != NULL){pHead = pHead->next;n++;}return n;}//非递归逆置ListNode* Reverse(ListNode* pHead){ListNode* pTemp = pHead;ListNode *pre,*plast = NULL;while(pTemp!= NULL){pre = pTemp->next; pTemp->next = plast;plast = pTemp;pTemp = pre;}return plast;}//递归逆置,关键是如何在递归中找到起点(原来的最后一点)ListNode* Reverse_recurve(ListNode* pHead){if(pHead == NULL || pHead->next == NULL )return pHead;ListNode *pHead1 = Reverse_recurve(pHead->next);pHead->next->next = pHead;pHead->next = NULL;return pHead1;}//用栈逆置ListNode* Reverse_stack(ListNode* pHead){stack<ListNode*> lstack;while(pHead != NULL){lstack.push(pHead);pHead = pHead->next;}pHead = lstack.top();ListNode* plast = pHead;ListNode* pre;lstack.pop();while(!lstack.empty()){pre = lstack.top();lstack.pop();plast->next = pre;plast = pre;}plast->next = NULL;return pHead;}//合并链表void merge(ListNode* pHead,int n){ListNode* pTemp1 = pHead,*pTemp2,*pTemp;if(n%2 == 0)n = n/2;elsen = n/2+1;while(n-1){pTemp1 = pTemp1->next;n--;}pTemp = pTemp1->next;pTemp1->next = NULL;//逆置pTemp = Reverse(pTemp);//合并while(pTemp != NULL){pTemp1 = pHead->next;pTemp2 = pTemp->next;pTemp->next = pHead->next;pHead->next = pTemp;pHead = pTemp1;pTemp = pTemp2;}return;}int main(){ListNode* pHead = NULL;AddToList(&pHead,1);AddToList(&pHead,2);AddToList(&pHead,3);AddToList(&pHead,4);AddToList(&pHead,5);//AddToList(&pHead,6);ListNode* pHead1 = pHead;pHead1 = Reverse(pHead1);pHead = pHead1;while(pHead1->next != NULL){printf("%d->",pHead1->value);pHead1 = pHead1->next;}printf("%d\n",pHead1->value);//递归pHead1 = pHead;pHead1 = Reverse_recurve(pHead1);pHead = pHead1;while(pHead1->next != NULL){printf("%d->",pHead1->value);pHead1 = pHead1->next;}printf("%d\n",pHead1->value);//栈pHead1 = pHead;pHead1 = Reverse_stack(pHead1);pHead = pHead1;while(pHead1->next != NULL){printf("%d->",pHead1->value);pHead1 = pHead1->next;}printf("%d\n",pHead1->value);//微软题目pHead1 = pHead;int len = ListLen(pHead);merge(pHead,len);while(pHead->next != NULL){printf("%d->",pHead->value);pHead = pHead->next;}printf("%d\n",pHead->value);system("PAUSE");return 0;}输出结果如下:
- 链表专题[三种逆置方式和微软笔试题]
- 微软笔试题和要点
- 微软笔试题和要点
- [转载] 微软笔试题
- 微软笔试题(zz)
- 微软笔试题3
- 微软笔试题4
- 微软笔试题一
- 微软笔试题
- 微软笔试题 汇总
- 2011微软笔试题
- 微软笔试题
- 微软笔试题
- 2011微软笔试题
- 微软笔试题
- 微软笔试题
- 微软笔试题:
- 微软PM笔试题
- 函数返回大类型方式
- ios开发过程中的小知识点
- Html,Css,Dom,javascript一些细节
- 如何在mysql中修改md5加密过的用户密码
- 该如何运营SEO策略
- 链表专题[三种逆置方式和微软笔试题]
- Android中全屏或者取消标题栏
- matlab的使用笔记
- 前端之Android入门(1):环境配置
- Objective-C中NSValue的使用
- 第三次作业
- sqlserver函数大全
- autolayout相关
- 1.1 软件架构概念的分类