反转链表和查找倒数第K个节点
来源:互联网 发布:.co.jp 日本域名 编辑:程序博客网 时间:2024/06/14 10:07
一:链表的逆置(反转链表)
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的头结点:
节点的结构
struct ListNode{ ListNode(const int& val) :_val(val) ,next(NULL) {} int _val; ListNode*next;};
这里面我们需要三个指针分别是cur,用来顺序遍历整个链表,newhead指针用来保存逆置的头结点,prev用来逆序遍历链表.
步骤:
1:先遍历整个链表找到当前节点的下一个节点为空,即为尾节点也是逆置后的头结点
2:prev用来保存当前节点的上一个节点.
3:然后更新节点的位置,把当前节点指针指向前一个节点,再把它的下一个指针指向当前位置,这样就可以保证所有节点链在一起了.
ListNode*ReverseList(ListNode*phead){ ListNode *cur =phead; ListNode*newhead=NULL; ListNode*prev =NULL; while(cur!=NULL) { ListNode*_next = cur->next; if(_next ==NULL) newhead =cur;//找到逆置后的头结点 cur->next =prev;//保存上一个节点 //更新当前节点的位置 prev = cur; cur =_next; } return newhead;}
二:查找倒数第k个节点
题目:输入一个链表,数除该链表的倒数第K个节点.
常规的思路是从尾到头开始遍历,然后就可以找到第k个节点,但是我们忽略了一个前提的条件就是这个链表时单向链表,不能从后先前遍历,因此这种方法行不通
既然从尾到头不能遍历我们还是从头遍历,那么如何找到倒数第k个节点呢?我们先假设链表有n个节点,那么倒数第K个节点就是从开始向后走n-k+1(n>k)步就好了,如何得到节点数n,遍历链表每遍历一个,计数器加1;
查找倒数第K个节点我们就要遍历遍历两次事件复杂度就是N^2,那么如何只遍历一次事件复杂度是0(N)呢?
方法:快慢指针
我们仔细分析下,
第一步:开始的时候假设快慢指针都指向首位置,
第二步:让快指针先走k-1步,慢指针不动,
第三步:快慢指针同时走,当快指针走两步的之后刚好到达链表的尾,而,慢指针走两步刚好到达K(值为3)的位置.
这样就可以实现查找倒数第k个目的.
ListNode *FindKthToTail(ListNode*phead,unsigned int k){//首先要判断头结点是否为空,以及k是否有效 if(phead ==NULL||k ==0) return NULL; ListNode*fast=phead; ListNode*slow =phead; for(unsigned i =0;i<k-1;i++) { //满足k小于结点的总数 if(fast->next ==NULL) { return NULL; } else{ fast =fast->next; } } while(fast->next!=NULL) { fast =fast->next; slow =slow->next; } return slow;}
三:验证:(C++实现)
#include<iostream>#include<stdlib.h>using namespace std;struct ListNode{ ListNode(const int& val) :_val(val) ,next(NULL) {} int _val; ListNode*next;};//逆置单链表ListNode*ReverseList(ListNode*phead){ ListNode *cur =phead; ListNode*newhead=NULL; ListNode*prev =NULL; while(cur!=NULL) { ListNode*_next = cur->next; if(_next ==NULL) newhead =cur; cur->next =prev; prev = cur; cur =_next; } return newhead;}//查找倒数第K个节点ListNode *FindNKToTail(ListNode*phead,unsigned int k){ if(phead ==NULL||k<0) return NULL; ListNode*fast=phead; ListNode*slow =phead; for(int i =1;i<k;i++) { if(fast->next ==NULL) { return NULL; } else{ fast =fast->next; } // fast =fast->next; } while(fast!=NULL&&fast->next!=NULL) { fast =fast->next; slow =slow->next; } return slow;}//添加节点ListNode* BuyNode(int x){ ListNode*node = (ListNode*)malloc(sizeof(ListNode)); node->_val = x; node->next = NULL; return node;}//打印单链表void PrintList(ListNode*phead){ ListNode*cur = phead; while(cur) { cout<<cur->_val<<"->"; cur =cur->next; } cout<<endl;}//创建单链表ListNode*CreatList(){ ListNode*head; ListNode*node1 = BuyNode(1); ListNode*node2 = BuyNode(2); ListNode*node3 = BuyNode(3); head=node1; node1->next =node2; node2->next =node3; node3->next =NULL; return node1;}void Test(){ cout<<"before"<<endl; ListNode*head =CreatList(); PrintList(head); // cout<<"after"<<endl; // ListNode*newhead =ReverseList(head); // PrintList(newhead); cout<<"查找倒数第K个节点"<<endl; ListNode*newhead1 =FindNKToTail(head,2); PrintList(newhead1);}
四: 实现一个Add函数,让两个数相加,但是不能使用+、-、*、/等四则运算符。ps:也不能用++、–等等
//位运算完成+,-
int add(int a,int b){ int c; while(c =(a&b)) { a =a^b; b= (c<<1); } return (a^b);}//减法,a取反再加1int sub(int a){ add(a,b); return add(~a,1);}int main(){ int a =-1; int b =-2; add(a,b); sub(a); cout<<add(a,b)<<endl; cout<<sub(a)<<endl; Test(); return 0;}
- 反转链表和查找倒数第K个节点
- 查找链表倒数第K个节点
- 查找链表倒数第k个节点
- 链表面试题/逆置/反转单链表+查找单链表的倒数第k个节点
- 逆置/反转单链表+查找单链表的倒数第k个节点,要求只能遍历一次链表
- 逆置/反转单链表+查找单链表的倒数第k个节点,要求只能遍历一次链表
- 查找单链表倒数第K个节点和以及逆置单链表
- 查找链表中倒数第K个节点
- 单链表查找倒数第k个节点
- 查找链表中倒数第k个节点
- 单链表查找倒数第k个节点
- 单链表中查找倒数第K个节点
- 单链表查找倒数第k个节点
- 查找单链表中倒数第k个节点
- 查找单链表中倒数第k个节点
- 链表倒数第k个节点
- 链表倒数第k个节点
- 链表倒数第k个节点
- html5跨域访问接口或者一般处理程序
- 【腾讯TMQ】老总让做后台接口监控,我却开发了一个App
- Fibonacci数列(string大整数)
- CodeForces 831B-Keyboard Layouts
- JAVA中的枚举类型
- 反转链表和查找倒数第K个节点
- 图像处理之Hessian矩阵提取关键点
- 自定义Toolbar以及使用
- 387. First Unique Character in a String(Java)
- android 中获取手机中安装的应用并做跳转的相关分析研究
- ipbrother告诉你方法,创建有意义的链接数!
- 软件测试就是找bug NO!
- android中 如何设置控件获取焦点
- [POJ1905]Expanding Rods