1.逆置(1.借助头结点2.不借助头结点)

cpp
void Reverse_List1(Node* plist)
{
//1.准备工作(申请两个指针p和q,分别指向第一个有效节点和第二个有效节点)
Node* p = plist->next;//第一个节点
Node* q = NULL;//Node*p=p->next;
//2.断开头结点
plist->next = NULL;
while (p != NULL)
{
q = p->next;
p->next = plist->next;
plist->next = p;
p = q;
}
}
cpp
struct ListNode* reverseList(struct ListNode* head) {
if(head==NULL)return NULL;
struct ListNode*p1=NULL;
struct ListNode*p2=head;
struct ListNode*p3=head->next;
while(p2!=NULL)
{
p2->next=p1;
p1=p2;
p2=p3;
if(p3!=NULL)
{
p3=p3->next;
}
}
return p1;
}
2.判断两个单链表是否存在交点,如果存交点,则找到相交的第一个点
2.1 如果面试官没有让找相交点,只是问你是否相交(可以用一个非常简单的方法)
cpp
Node* Intersect(Node* plist1, Node* plist2)
{
Node* p = plist1;
Node* q = plist2;
for (; p != NULL; p = p->next);
for (; q != NULL; q = q->next);
if (q != p)
return NULL;
}
2.2如果面试官既要判断是否相交,还要问你相交点在哪(另外一种解题思路)


cpp
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA == NULL || headB == NULL) return NULL; // 修改:检查空链表而不是next
int i=0,j=0;
int sum=0;
struct ListNode *p1=headA;
struct ListNode *p2=headB;
while(p1!=NULL)
{
p1=p1->next;
i++;
}
while(p2!=NULL)
{
p2=p2->next;
j++;
}
p1 = headA;
p2 = headB;
if(i>j)sum=i-j;
else if(i<j)sum=j-i;
if(i>j)
{
while(sum>0)
{
p1=p1->next;
sum--;
}
}
if(i<j){
while(sum>0)
{
p2=p2->next;
sum--;
}
}
while(p1 != NULL && p2 != NULL)
{
if(p1==p2)return p1;
else{
p1=p1->next;
p2=p2->next;
}
}
return NULL;
}
3.任意删除一个节点(要求时间复杂度为0(1),给的这个节点的地址不能是尾结点)
cpp
bool Delete(Node* p)
{
assert(p != NULL);
if (p->next == NULL)return false;
Node* q = p->next;
p->data = q->data;
Node* r = q->next;
p->next = r;
free(r);
r = NULL;
return true;
}
4.1.判断一个单链表是否存在环 2如果确存在环,则找到入环点

cpp
bool hasCycle(struct ListNode *head) {
if(head==NULL)return false;
if(head->next==NULL)return false;
struct ListNode *p=head;
struct ListNode *q=head->next;
while(q != NULL && q->next != NULL)
{
if(q==p)
{
return true;
}
else
{
p=p->next;
q=q->next->next;
}
}
return false;
}
cpp
Node* Find_FristCirCleNode(Node* plist)
{
if (Is_Empty(plist))
return NULL;
Node* slow = plist;
Node* quick = plist;
slow = slow->next;
quick = quick->next->next;
while (quick != NULL && quick != slow)
{
slow = slow->next;
//quick = quick->next->next; //bug
quick = quick->next;
if (quick != NULL)
quick = quick->next;
}
if (quick == NULL)
{
return NULL;
}
//怎么找入环点:让两个指针,1个从初始位置出发,1个从快慢指针相遇点出发,
保持同样的速度,当这两个指针相遇的时候,相遇节点就是找的第一个入环点
Node* p = plist;
Node* q = quick;//slow
while (p!=q)
{
p = p->next;
q = q->next;
}
return p;//q
}
5.确定一个单链表是否回文12321(ES)123321(YES)123(YES)
5.1借助栈来实现
5.2除2队后面的链表进行逆置
cpp
#include <stack>
bool Is_Palindrome(Node* plist)
{
std::stack<Node*> st;
int len = Get_Length(plist);
Node* p = plist->next;
for (int i = 0; i < len / 2; i++)
{
st.push(p);
p = p->next;
}
if (len % 2 == 1)
p = p->next;
while (!st.empty() && p != NULL)
{
if (st.top()->data != p->data)
{
return false;
}
else
{
p = p->next;
st.pop();
}
}
return true;
}
cpp
struct ListNode* reverseList(struct ListNode* head) {
if(head==NULL)return NULL;
struct ListNode*p1=NULL;
struct ListNode*p2=head;
struct ListNode*p3=head->next;
while(p2!=NULL)
{
p2->next=p1;
p1=p2;
p2=p3;
if(p3!=NULL)
{
p3=p3->next;
}
}
return p1;
}
bool isPalindrome(struct ListNode* head){
if(head==NULL)return false;
if(head->next==NULL)return true;
int i=0;
struct ListNode*p=head;
while(p!=NULL)
{
p=p->next;
i++;
}
p=head;
for(int j=0;j<i/2;j++)
{
p=p->next;
}
if(i%2==1)
{
p=p->next;
}
struct ListNode* r=reverseList(p);
struct ListNode*q=head;
while(r!=NULL)
{
if(q->val!=r->val)return false;
else
{
r=r->next;
q=q->next;
}
}
return true;
}
6.找到单链表倒数第K个节点
cpp
int kthToLast(struct ListNode* head, int k) {
struct ListNode*p=head;
struct ListNode*q=head;
for(;k!=0;k--)
{
q=q->next;
}
while(q!=NULL)
{
p=p->next;
q=q->next;
}
return p->val;
}