一:链表的逆置(反转链表)
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的头结点:
节点的结构
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取反再加1
int 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;
}