题一:链表逆序a Leetcode 206
描述
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
思路:
比较简单
遍历链表
每到一个结点逆转一个
解法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL){return head;}
if(head->next==NULL){return head;}
else{
ListNode * tmp1=NULL;
ListNode * tmp2=head;
while(tmp2!=NULL)
{
ListNode * tmp=tmp2->next;
tmp2->next=tmp1;
tmp1=tmp2;
tmp2=tmp;
}
return tmp1;
}
}
};
题二:链表逆序b LeetCode 92
描述:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
思路:
找到指定位置的结点m和结点n 以及结点m-1 和结点n+1
解法 :
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode * root = new ListNode(0); //此节点的next指向head 方便后面找到m和n的位置
root->next = head;
ListNode * p = root,* q = root;
m--;
while(m--) p = p->next; // 位置m-1处的结点p
while(n--) q = q->next; // 位置n处的结点q
ListNode * tail = q->next;//位置n+1处的结点tail
ListNode * curr = p->next;//位置m处的结点curr
//开始逆转
ListNode * pro = tail;
q->next = NULL;
while(curr)
{
ListNode * tmp = curr->next;
curr->next = pro;
pro = curr;
curr = tmp;
}
p->next = pro;
return root->next;
}
};
题三: 两个链表的交点 LeetCode 160
描述
思路
解法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int len_a =0,len_b=0;
ListNode * tmp_a=headA,*tmp_b=headB;
//计算两个链表长度
while(tmp_a!=NULL){len_a++;tmp_a=tmp_a->next;}
while(tmp_b!=NULL){len_b++;tmp_b=tmp_b->next;}
if(len_a>=len_b){//如果a链表长度大于b链表长度
int dis=len_a-len_b;
ListNode *new_headA=headA;
while(dis!=0){new_headA=new_headA->next; dis--;}//把a链表头结点移动到相应位置
while((new_headA!=headB)&&(headB!=NULL)&&(new_headA!=NULL)){new_headA=new_headA->next;headB=headB->next;}//找到相交点
return headB;
}
else//如果b链表长度大于a链表长度
{
int dis=len_b-len_a;
ListNode *new_headB=headB;
while(dis!=0){new_headB=new_headB->next; dis--;}//把b链表头结点移动到相应位置
while((new_headB!=headA)&&(headA!=NULL)&&(new_headB!=NULL)){new_headB=new_headB->next;headA=headA->next;}//找到相交点
return headA;
}
}
};
题四:链表求环 Leetcode 141
描述
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
思路
用快慢指针解决
慢指针slow每次走一步
快指针fast每次走两步
这样 如果链表有环 则他们必定会在环内相遇(这是一个定理)
证明如下:
解法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head==NULL||head->next==NULL||head->next->next==NULL){return false;}
ListNode *slow =head;
ListNode *fast=head->next->next;
while(slow!=fast)
{
if(fast==NULL||fast->next==NULL){return false;}
slow=slow->next;
fast=fast->next->next;
}
return true;
}
};
题五 :链表划分 LeetCode 86
描述:
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
示例:
输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
思路:
建立两个临时结点
r然后遍历该链表
大的元素放在第一个临时结点建立的链表里面
小的元素放在第二个临时结点建立的链表里面
题解:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode* tmp_head1=new ListNode(0);
ListNode* tmp_head2=new ListNode(0);
ListNode* flag2=tmp_head2;
ListNode* flag1=tmp_head1;
ListNode*tmp=head;
while(head){
if(head->val>=x){tmp_head2->next=head; tmp_head2=head;}
else{tmp_head1->next=head; tmp_head1=head;}
head=head->next;
}
tmp_head1->next=flag2->next;
tmp_head2->next=NULL;
return flag1->next;
}
};
题六:两个排序链表合并 Leetcode 21
描述:
思路:
题解:
题七:多个排序链表合并 Leetcode 23
描述:
思路:
题解:
题八:从尾到头打印链表 剑指offer
描述:
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
实现:
题九 链表倒数第K个结点 剑指offer
描述:
输入一个链表,输出该链表中倒数第k个结点。
题解:
题十: 删除链表中重复的结点 剑指offer
描述:
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
例如,链表1->2->3->3->4->4->5 处理后为 1->2->5