1.反转一个链表,不能申请新空间:
思路:反转一个链表,不申请新空间,即将一个链表通过头插+头删的方法进行替换;
反转前:1->2->3->4->5->NULL;
反转后:NULL->5->4->3->2->1;
struct ListNode* Reverselist(struct ListNode* head){
struct ListNode* result=NULL;
struct ListNode* code=head;
while(code!=NULL){
struct ListNode* next=code->next;
code->next=result;
result=code;
code=next;
}
return result;
}
2.删除表中指定的所有节点:
思路:判断链表的的节点的值是否为指定节点的值有三种情况:
(1)当头节点为空时的情况;
(2)当头节点为指定节点的值时的情况;
(3)当头节点不是指定节点时的情况;
struct ListNode* RemoveElement{struct ListNode *head,int val){
if(head==NULL){ //判断头节点是否为空;
return 0;
}
struct ListNode* Node=head;
while(Node->next!=NULL){ //链表中的指定节点删除;
if(Node->next->val==val){
struct ListNode* next=Node->next->next;
free(Node->next);
Node->next=next;
}
else{
Node=Node->next;
}
if(head->val==val){ //当头节点是想要删除的节点;
struct ListNode* second=head->next;
free(head);
return second;
}
else{
return head;
}
3.合并两个有序链表:
将两个链表合并成一个有序链表,并返回;新链表是通过拼接两个链表所给定的链表的值;
如:1->2->4,1->3->4;
拼接后:1->1->2->2->3->4->4;
struct ListNode* MergoTwoList(struct Listnode* L1,struct ListNode* L2){
//先判断两个链表是否为空;
if(L1==NULL){
return L2;
}
if(L2==NULL){
return L1;
}
//创建一个新链表,将两个拼接的链表放到新链表中;
struct ListNode* L1=c1;
struct ListNode* L2=c2;
struct ListNode* begin=NULL;
struct ListNode* end=NULL;
while(c1!=NULL&&c2!=NULL){
if (c1->val <=c2->val){
if (last != NULL){
last->next = c1;
last = c1;
}
else{
result = last = c1;
}
c1 = c1->next;
}
else{
if (last != c2){
last->next = c2;
last = c2;
}
else{
result = last = c2;
}
c2 = c2->next;
}
}
if (c1!= NULL){
last->next = c1;
}
if (c2 != NULL){
last->next = c2;
}
return result;
}
4.分割链表问题:
编写代码,给定一个值x为基准,将链表分割为两部分,所有小于x的结点排在大于或等于x的链表之前;分割以后要保持原来的数据顺序不变;
思路:一个小于x的结果链表,一个大于等于x的结果链表,根据和x的关系,尾插到不同的链表中,把两个链表链接起来;
注意:需要注意比x小的或比x大的链表有为空的情况;一定要保证结果链表的最后一个节点为NULL;
struct ListNode *partition(struct ListNode *PHead, int x){
struct ListNode *small = NULL;
struct ListNode *smallLast = NULL;
struct ListNode *big = NULL;
struct ListNode *bigLast = NULL;
struct ListNode *node = PHead;
while (node != NULL){
if (node->val < x){
if (small == NULL){
small = smallLast = node;
}
else {
smallLast->next = node;
smallLast = node;
}
}
else{
if (big == NULL){
big = bigLast = node;
}
else{
bigLast->next = node;
bigLast = node;
}
}
node = node->next;
}
if (smallLast != NULL){
smallLast->next = big;
}
if (bigLast != NULL){
bigLast->next = NULL;
}
if (smallLast != NULL){
return small;
}
else{
return big;
}
}
5.返回链表的中间节点:
给定一个带有头结点head的非空单链表,返回链表的中间结点,如果两个中间结点,则返回第二个中间结点;在这里考察的主要是指针的运用,通过快慢指针进行遍历,当一个指针指向NULL时,另一个指针刚好指向该链表的中间节点;
struct ListNode *middleNode(struct ListNode * head){
struct ListNode *fast = head;
struct ListNode *slow = head;
while (fast!=NULL){
fast = fast->next;
if (fast == NULL){
break;
}
slow = slow->next;
fast = fast->next;
}
return slow;
}
6.删除链表中的重复节点问题:
在一个排序的链表中存在着重复得结点,请删除该链表中的重复结点,重复的结点不保留,返回链表头指针;如:链表1->2->3->3->4->4->5,处理后为1->2->3->4->5;
这里可以通过双指针遍历去查找,当前面的指针指向的节点的值与后一个指针指向节点的值相同时,后面的指针指向的位置不变,前面的指针继续向前走,当两个指针指向的值不同时,后面的指针走到前面的指针的位置,前面的指针继续向前寻找,知道遇到NULL;
struct ListNode *deleteDuplication(struct ListNode * pHead){
if (pHead == NULL){
return NULL;
}
struct ListNode *fack = (ListNode *)malloc(sizeof(ListNode));
fack->next = pHead;
struct ListNode * prev = fack;
struct ListNode * p1 = pHead;
struct ListNode * p2 = pHead->next;
while (p2 != NULL){
if (p1->val != p2->val){
prev = p1;
p1 = p2;
p2 = p2->next;
}
else{
while (p2 != NULL && p2->val == p1->val){
p2 = p2->next;
}
prev->next = p2;
p1 = p2;
if (p2 != NULL){
p2 = p2->next;
}
}
}
pHead = fack->next;
free(pHead);
return fack->next;
}
7.找到两链表交叉的起始节点:
//先求出链表的长度;
int getLength(struct ListNode * head){
int len = 0;
for (struct ListNode *n = head; n; n->next->next){
len++;
}
return len;
}
struct ListNode *getIntersectionNode(struct ListNode *PheadA, struct ListNode *PheadB){
int lenA = getLength(PheadA);
int lenB = getLength(PheadB);
struct ListNode * longer = PheadA;
struct ListNode * shorter = PheadB;
int diff=lenA - lenB;
if (lenB > lenA)
{
longer = PheadB;
shorter = PheadA;
diff == lenB - lenA;
}
for (int i = 0; i < diff; ++i){
longer = longer->next;
}
while (longer != shorter){
longer = longer->next;
shorter = shorter->next;
}
return longer;
}
8.判断链表是否带环,找到环的入口点:
struct ListNode *detcctCycle(struct ListNode *head){
if (head == NULL){
return NULL;
}
struct ListNode* fast = head;
struct ListNode *slow = head;
while (1){
fast = fast->next;
if (fast == NULL){
return NULL;
}
fast = fast->next;
if (fast == NULL){
return NULL;
}
slow = slow->next;
if (fast == slow){
break;
}
}
struct ListNode * n1 = head;
struct ListNode *n2 = slow;
while (n1 != n2){
n1 = n1->next;
n2 = n2->next;
}
return n1;
}