203. 移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode *prev,*cur;
cur=head;
prev=NULL;
while(cur)
{
if(cur->val==val)
{
struct ListNode *next=cur->next;
free(cur);
if(prev==NULL)//if(cur==head)
head=next;//删除第一个
else
prev->next=next;
cur=next;//这个要分开
}
else
{
prev=cur;
cur=cur->next;
}
}
return head;
}
206. 反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
第一种解法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
//头插完成单链表逆转
//头插就是这个位置的next是现在的head;然后这个位置在变成head
struct ListNode *newHead=NULL;
struct ListNode *cur=head;
while(cur)
{
struct ListNode *next=cur->next;
cur->next=newHead;
newHead=cur;
cur=next;
}
return newHead;
}
第二种解法:
struct ListNode* reverseList(struct ListNode* head){
if(head==NULL||head->next==NULL)
return head;
struct ListNode *n1,*n2,*n3;
n1=NULL;
n2=head;
n3=n2->next;
while(n2)
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
}
876. 链表的中间结点
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* middleNode(struct ListNode* head){
//快慢节点
struct ListNode *fast,*slow;
fast=head;
slow=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
链表中的倒K个节点
输入一个链表,输出该链表中倒数第k个结点。
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
// write code here
//距离差,快的先走k
//然后快的到空,慢的就到了倒数第k
struct ListNode *fast,*slow;
fast=slow=pListHead;
while(k--)
{
if(fast)
fast=fast->next;
else
return NULL;//k>链表长度
}
//存在
while(fast)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if(l1==NULL)
return l2;
if(l2==NULL)
return l1;
struct ListNode *cur1,*cur2,*newHead,*newTail;
cur1=l1;
cur2=l2;
newHead=newTail=NULL;
while(cur1&&cur2)
{
if(cur1->val<=cur2->val)
{
if(newTail==NULL)
newHead=newTail=cur1;
else
{
newTail->next=cur1;
newTail=newTail->next;
}
cur1=cur1->next;
}
else
{
if(newTail==NULL)
newHead=newTail=cur2;
else
{
newTail->next=cur2;
//表尾记录,下一个位置是什么,在把下一个位置变成表尾
newTail=newTail->next;//表尾拼接
}
cur2=cur2->next;
}
}
//拷贝剩余元素
if(cur1)
{
newTail->next=cur1;
}
if(cur2)
{
newTail->next=cur2;
}
return newHead;
}
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if(l1==NULL||l2==NULL)
return l1==NULL?l2:l1;
struct ListNode *cur1,*cur2,*newHead,*newTail;
newHead=newTail=(struct ListNode*)malloc(sizeof(struct ListNode));
cur1=l1;
cur2=l2;
while(cur1&&cur2)
{
if(cur1->val<=cur2->val)
{
newTail->next=cur1;
newTail=newTail->next;
cur1=cur1->next;
}
else
{
newTail->next=cur2;
newTail=newTail->next;
cur2=cur2->next;
}
}
if(cur1)
newTail->next=cur1;
if(cur2)
newTail->next=cur2;
struct ListNode *head=newHead->next;
free(newHead);
return head;
}
}
链表分割
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。
//开空间的做法
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
// write code here
struct ListNode *cur,*lessHead,*lessTail,*greatHead,*greatTail;
cur=pHead;
lessHead=lessTail=(struct ListNode*)malloc(sizeof(struct ListNode));
greatHead=greatTail=(struct ListNode*)malloc(sizeof(struct ListNode));
while(cur)
{
if(cur->val<x)
{
lessTail->next=cur;
lessTail=lessTail->next;
cur=cur->next;
}
else{
greatTail->next=cur;
greatTail=greatTail->next;
cur=cur->next;
}
}
if(greatTail)
greatTail->next=NULL;
lessTail->next=greatHead->next;
struct ListNode *head=lessHead->next;
free(lessHead);
free(greatHead);
return head;
}
};
链表的回文结构
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// write code here
if(A==NULL||A->next==NULL)
return true;
struct ListNode *fast,*slow,*start1,*start2;
start1=fast=slow=A;
//找到中间节点
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
}
//后半部分逆转
struct ListNode *n1,*n2,*n3;
n1=NULL;
n2=slow;
n3=n2->next;
while(n2->next)
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3->next)
n3=n3->next;
}
start2=n2;
//遍历
while(start1&&start2)
{
if(start1->val!=start2->val)
{
return false;
}
start1=start1->next;
start2=start2->next;
}
return true;
}
160. 相交链表
编写一个程序,找到两个单链表相交的起始节点
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int lenA=0;
int lenB=0;
struct ListNode *curA=headA;
struct ListNode *curB=headB;
while(curA)
{
++lenA;
curA=curA->next;
}
while(curB)
{
++lenB;
curB=curB->next;
}
curA=headA;
curB=headB;
int gab=abs(lenA-lenB);
if(lenA>lenB)
{
while(gab--)
{
curA=curA->next;
}
}
else
{
while(gab--)
{
curB=curB->next;
}
}
while(curA&&curB)
{
if(curA==curB)
{
return curA;
}
curA=curA->next;
curB=curB->next;
}
return NULL;
}
141. 环形链表
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
bool hasCycle(struct ListNode *head) {
struct ListNode *fast,*slow;
fast=slow=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
return true;
}
return false;
}
142. 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//先判断是否有环
struct ListNode* hasCycle(struct ListNode *head) {
struct ListNode *fast,*slow;
fast=slow=head;
while(fast&&fast->next)
{
//距离差是一步,可以确保追上,步数大了就不太行
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
return fast;//fast是相遇点,不一定是环的第一个节点
}
return NULL;
}
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *cur=hasCycle(head);
if(cur)
{
while(cur)
{
if(cur==head)
return cur;
cur=cur->next;
head=head->next;
}
}
return NULL;
}
138. 复制带随机指针的链表
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head) {
//拷贝数据
if(head==NULL)
return head;
struct Node *cur=head;
while(cur)
{
struct Node *newNode=(struct Node*)malloc(sizeof(struct Node));//一定要注意,这次又给忘记了
newNode->val=cur->val;
newNode->next=cur->next;//先赋值,再改指向
cur->next=newNode;
cur=newNode->next;
}
//拷贝随机指针
cur=head;
while(cur)
{
struct Node *copy=cur->next;
if(cur->random)
{
copy->random=cur->random->next;
}
else
copy->random=NULL;
cur=copy->next;
}
//拆链
struct Node *newHead=NULL;
cur=head;
while(cur)
{
struct Node *copy=cur->next;
struct Node *next=copy->next;
cur->next=next;
if(newHead==NULL)
newHead=copy;
if(next)
copy->next=next->next;
cur=next;
}
return newHead;
}
147. 对链表进行插入排序
对链表进行插入排序
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* insertionSortList(struct ListNode* head){
if(head==NULL||head->next==NULL)
return head;
struct ListNode *node=head->next;
struct ListNode *tail=head;
while(node)
{
if(node->val<tail->val)
{
struct ListNode *prev=NULL;
struct ListNode *cur=head;
while(cur&&cur->val<=node->val)//从第一个开始找
//找到第一个大于node的值,cur大于node
{
prev=cur;
cur=cur->next;//同时向后移动
}
tail->next=node->next;
//可能在头部插入
if(prev)
prev->next=node;
else
head=node;
node->next=cur;
//下一个数据的排序,tail不变
node=tail->next;
}
else
{
node=node->next;
tail=tail->next;
}
}
return head;
}