OJ链接
prev->next = cur->next
,free(cur)
(只有当头结点不为空且不需要删除时,才会用到prev指针)。//code-1:
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* cur = head;
//1.特殊情况,链表为空
if(cur == NULL)
return head;
//2.特殊情况,链表中的所有结点的val都等于目标值,需全部删除
while(cur && cur->val == val)
{
struct ListNode* del = cur;
cur = cur->next;
free(del);
//del是局部变量,不需要再置空
}
//更新头结点
head = cur;
//出2的循环时,要么cur为空,要么cur->val!=val
//3.常规情况
struct ListNode* prev = cur;
//prev->val!=val
if(prev)
{
cur = prev->next;
//如果要删除,就删除cur结点
while(cur)
{
//需要删除
if(cur->val == val)
{
prev->next = cur->next;
free(cur);
cur = prev->next;
}
else
{
prev = cur;
cur = cur->next;
}
}
}
return head;
}
prev->next = cur->next
,free(cur)
。再更新cur。//code-2
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* cur = head;
struct ListNode* prev = NULL;//指向要删除结点的上一个结点
while(cur)
{
//需要删除当前结点
if(cur->val == val)
{
//需要删除的结点是头结点
if(cur == head)
{
head = head->next;
free(cur);
cur = head;
}
else//删除非头节点
{
//常规情况的删除
prev->next = cur->next;
free(cur);
cur = prev->next;
}
}
else
{
prev = cur;
cur = cur->next;
}
}
return head;
}
//code-1: 不带哨兵位结点
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* newHead, *tail;
newHead = tail = NULL;
struct ListNode* cur = head;
while(cur)
{
if(cur->val != val)
{
if(tail == NULL)
{
newHead = tail = cur;
}
else
{
tail->next = cur;
tail = tail->next;
}
cur = cur->next;
}
else
{
struct ListNode* del = cur;
cur = cur->next;
free(del);//局部变量,不需要再置为空
}
}
//新链表结尾置为空
if(tail)//防止解引用空指针
tail->next = NULL;
return newHead;
}
//code-2: 带哨兵位结点 (推荐)
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* cur = head;
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
assert(guard);
struct ListNode* tail = guard;
while(cur)
{
if(cur->val != val)
{
tail->next = cur;
cur = cur->next;
tail = tail->next;
}
else
{
struct ListNode* del = cur;
cur = cur->next;
free(del);
}
}
//注意,一定要判断tail是否为空
if(tail)
tail->next = NULL;
head = guard->next;
free(guard);
return head;
}
算法复杂度: 时间复杂度:O(n),空间复杂度:O(1)。
OJ链接
struct ListNode* reverseList(struct ListNode* head){
//head为空,或head->next为空,就没必要反转
if(!head || !head->next)
{
return head;
}
struct ListNode* cur = head->next;
struct ListNode* newHead = head;
while(cur)
{
head->next = cur->next;
cur->next = newHead;
newHead = cur;
cur = head->next;
}
return newHead;
}
算法复杂度: 时间:O(n),空间O(1)。
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* prev = NULL, *cur = head;
while(cur)
{
struct ListNode* next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
算法复杂度: 时间:O(n),空间:O(1)。
OJ链接
解析:
struct ListNode* middleNode(struct ListNode* head){
struct ListNode* fast, *slow;
fast = slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
OJ链接
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
struct ListNode* fast, *slow;
fast = slow = pListHead;
//先让fast走k步
while(fast && k--)
{
fast = fast->next;
}
//k>链表长度
if(k > 0)
return NULL;
while(fast)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
OJ链接
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
assert(guard);
guard->next = NULL;
struct ListNode* tail = guard;
struct ListNode* cur1 = list1, *cur2 = list2;
while(cur1 && cur2)
{
if(cur1->val < cur2->val)
{
tail->next = cur1;
tail = tail->next;
cur1 = cur1->next;
}
else
{
tail->next = cur2;
tail = tail->next;
cur2 = cur2->next;
}
}
if(cur1)
{
tail->next = cur1;
}
if(cur2)
{
tail->next = cur2;
}
return guard->next;
}
OJ链接
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
struct ListNode* LessGuard, *LessTail, *GreaterGuard, *GreaterTail;
LessGuard = (ListNode*)malloc(sizeof(ListNode));
GreaterGuard = (ListNode*)malloc(sizeof(ListNode));
assert(LessGuard && GreaterGuard);
LessTail = LessGuard;
GreaterTail = GreaterGuard;
GreaterTail->next = LessTail->next = NULL;//也可以不写
ListNode* cur = pHead;
while(cur)
{
if(cur->val < x)
{
LessTail->next = cur;
LessTail = LessTail->next;
//cur = cur->next;
}
else
{
GreaterTail->next = cur;
GreaterTail = GreaterTail->next;
//cur = cur->next;
}
cur = cur->next;
}
LessTail->next = GreaterGuard->next;
GreaterTail->next = NULL;//注意,这一步不能省略
pHead = LessGuard->next;
free(LessGuard);
free(GreaterGuard);
return pHead;
}
};
OJ链接
题目要求:
解析:
//找中间结点
struct ListNode* middleNode(struct ListNode* head){
struct ListNode* fast, *slow;
fast = slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
//翻转链表
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* prev = NULL;
struct ListNode* cur = head;
while(cur)
{
struct ListNode* next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
bool isPalindrome(struct ListNode* head){
struct ListNode* mid = middleNode(head);
struct ListNode* rmid = reverseList(mid);
struct ListNode* cur = head;
while(cur && rmid)
{
if(cur->val != rmid->val)
return false;
cur = cur->next;
rmid = rmid->next;
}
return true;
}
算法复杂度: 时间:O(n),空间:O(1)。
OJ链接
解析:
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) {
if (!headA || !headB)
return NULL;
struct ListNode* cur1 = headA;
struct ListNode* cur2 = headB;
int len1 = 1;
int len2 = 1;
//找尾结点,并记录链表长度
while (cur1->next)
{
cur1 = cur1->next;
len1++;
}
while (cur2->next)
{
cur2 = cur2->next;
len2++;
}
//两链表不交叉
if (cur1 != cur2)
{
return NULL;
}
//
struct ListNode* LongList = headA;
struct ListNode* ShortList = headB;
if (len1 < len2)
{
LongList = headB;
ShortList = headA;
}
//长度的差值
int gap = abs(len1 - len2);
//长的先走差值步
while (gap--)
{
LongList = LongList->next;
}
//同时走
while (LongList != ShortList)
{
LongList = LongList->next;
ShortList = ShortList->next;
}
return LongList;
}
bool hasCycle(struct ListNode *head) {
struct ListNode* slow, *fast;
slow = fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//相遇即带环
if(fast == slow)
return true;
}
return false;
}
为什么满指针每次走一步,快指针每次走两步可以?
假设链表带环,那么最终慢指针和快指针都会进环。快指针先进环,慢指针后进环。最坏的情况是:慢指针刚进环时,快指针恰好在慢指针前面一步(环内),此时两者之间的距离是环的长度-1。慢指针走一步,快指针走两步,(可以根据相对运动的角度理解:慢指针不动,快指针走一步),每次两指针之间的距离都会-1,那么最终就一定会追上。
快指针每次走3步、4步、… … 、n步可以吗?
假定快指针每次走3步,环的长度为C。慢指针进环时,两指针之间的距离是X。每次循环(走)两指针之间的距离X减2。
- 如果进环时,环长C是偶数,两指针之间的距离X也是偶数,最终,会追上(fast==slow);
- 如果进环时,环长C是偶数,两指针之间的距离X是奇数,每次距离减2,最终,两指针会错过(fast ==slow->next),此时两指针之间的距离X是C-1(奇数),每次距离减2,就会永远错过,不会相遇(fast ==slow)。
法一(推荐):
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* fast = head, *slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(fast == slow)
{
struct ListNode* meet = slow;
struct ListNode* cur = head;
//一个指针从头走,同时另一个指针从相遇点走,两者会在入环的第一个结点相遇
while(meet != cur)
{
cur = cur->next;
meet = meet->next;
}
return meet;
}
}
return NULL;
}
//求相交链表的第一个公共结点
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) {
if (!headA || !headB)
return NULL;
struct ListNode* cur1 = headA;
struct ListNode* cur2 = headB;
int len1 = 1;
int len2 = 1;
//找尾结点,并记录链表长度
while (cur1->next)
{
cur1 = cur1->next;
len1++;
}
while (cur2->next)
{
cur2 = cur2->next;
len2++;
}
//两链表不交叉
if (cur1 != cur2)
{
return NULL;
}
//
struct ListNode* LongList = headA;
struct ListNode* ShortList = headB;
if (len1 < len2)
{
LongList = headB;
ShortList = headA;
}
//长度的差值
int gap = abs(len1 - len2);
//长的先走差值步
while (gap--)
{
LongList = LongList->next;
}
//同时走
while (LongList != ShortList)
{
LongList = LongList->next;
ShortList = ShortList->next;
}
return LongList;
}
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow = head, *fast = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
struct ListNode* meet = slow;
struct ListNode* next = meet->next;
//将环断开,变成相交链表问题
meet->next = NULL;
struct ListNode* entryNode = getIntersectionNode(head, next);
meet->next = next;
return entryNode;
}
}
return NULL;
}
random->next
。struct Node* copyRandomList(struct Node* head) {
struct Node* cur = head;
struct Node* copy = NULL;
struct Node* next = NULL;
//复制
while(cur)
{
copy = (struct Node*)malloc(sizeof(struct Node));
assert(copy);
copy->val = cur->val;
next = cur->next;
cur->next = copy;
copy->next = next;
//后移
cur = next;
}
//链接random指针
cur = head;
while(cur)
{
copy = cur->next;
if(cur->random == NULL)
copy->random = NULL;
else
copy->random = cur->random->next;
cur = cur->next->next;
}
//还原原链表
struct Node* copyhead = NULL, *copytail = NULL;
cur = head;
while(cur)
{
copy = cur->next;
next = copy->next;
//取copy结点 尾插
if(copytail == NULL)
{
copyhead = copytail = copy;
}
else
{
copytail->next = copy;
copytail = copytail->next;
}
//恢复原链表
cur->next = next;
cur = next;
}
return copyhead;
}
算法复杂度: 时间:O(N),空间:O(1)。