21.合并两个有序链表
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
int flag=0;
struct ListNode *p,*tmp,*q;
if(l1==NULL)
return l2;
if(l2==NULL)
return l1;
if(l1->val<=l2->val)
{p=l1; q=l2; flag=1;}
else
{p=l2; q=l1;}
while(p&&q)
{
if(p->next ==NULL)
break;
if(p->val<=q->val && p->next->val>=q->val )
{
tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
tmp->next=p->next;
tmp->val=q->val;
p->next=tmp;
q=q->next;
}
p=p->next;
}
if(q)
p->next=q;
if(flag)
return l1;
else
return l2;
}
83.删除排序链表中的重复元素
struct ListNode* deleteDuplicates(struct ListNode* head){
struct ListNode *p=(struct ListNode*)malloc(sizeof(struct ListNode)),
*tmp=(struct ListNode*)malloc(sizeof(struct ListNode)),
*tmphead=(struct ListNode*)malloc(sizeof(struct ListNode));
int val=0;
p->next=NULL;
tmp->next=NULL;
tmphead->next=NULL;
tmphead=head;
while(tmphead)
{
p=tmphead;
tmp=p->next;
val=p->val;
while(tmp)
{
if(tmp->val==val)
{
p->next=tmp->next;
tmp=p->next;
continue;
}
p=p->next;
tmp=p->next;
}
tmphead=tmphead->next;
}
return head;
}
141.环形链表
bool hasCycle(struct ListNode *head) {
if(head==NULL){
return 0;
}
struct ListNode *p,*q;
p=head;q=head;
while(p->next!=NULL&&q->next!=NULL){
if(p->next==q->next->next){
return 1;
}
p=p->next;q=q->next->next;
if(p==NULL||q==NULL){
return 0;
}
}
return 0;
}
160.相交链表
暴力法
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *p=(struct ListNode*)malloc(sizeof(struct ListNode)),
*q=(struct ListNode*)malloc(sizeof(struct ListNode));
p=headA;
q=headB;
while(p)
{
while(q&&p!=q)
q=q->next;
if(q)
break;
p=p->next;
q=headB;
}
if(p)
return p;
else
return NULL;
}
长度差法
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *p = headA, *q = headB;
int la, lb, lgap;
for (la = 0; p; p = p->next, la++);
for (lb = 0; q; q = q->next, lb++);
lgap = la - lb;
p=headA;
q=headB;
if (la > lb){
while (lgap--) p = p->next;
} else {
while (lgap++) q = q->next;
}
while (p){
if (p == q) return p;
p = p->next;
q = q->next;
}
return NULL;
}
通过“增加”消除长度差
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
if(headA==NULL||headB==NULL)return NULL;
struct ListNode* pA=headA;
struct ListNode* pB=headB;
while(pA!=pB)
{
pA=pA==NULL?headB:pA->next;
pB=pB==NULL?headA:pB->next;
}
return pA;
}
203.移除链表元素
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode *p=(struct ListNode*)malloc(sizeof(struct ListNode)),
*tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
p->next=NULL;
tmp->next=NULL;
while(head&&head->val==val)
head=head->next;
if(head==NULL)
return head;
p=head;
tmp=p->next;
while(tmp)
{
if(tmp->val==val)
{p->next=tmp->next;
tmp=p->next;
continue;}
if(p->next==NULL)
break;
p=p->next;
tmp=p->next;
}
return head;
}
206.反转链表
//处理思维比较复杂的时候,先要明确每个变量的职能,别太急
//思路:tmp用来保存原链,p是原链头,rehead是新链头
struct ListNode* reverseList(struct ListNode* head){
struct ListNode *p,*tmp,*rehead;
p=(struct ListNode *)malloc(sizeof(struct ListNode));
tmp=(struct ListNode *)malloc(sizeof(struct ListNode));
rehead=(struct ListNode *)malloc(sizeof(struct ListNode));
p->next=NULL;
tmp->next=NULL;
rehead=NULL;
p=head;
while(p)
{
tmp=p->next; //保存原始链结构
p->next=rehead; //将后节点next指向前节点
rehead=p; //新链换头为后节点
p=tmp; //p重新指向原始链头
}
return rehead;
}
234.回文链表
bool isPalindrome(struct ListNode* head){
struct ListNode *p,*tmp,*rehead;
p=(struct ListNode *)malloc(sizeof(struct ListNode));
tmp=(struct ListNode *)malloc(sizeof(struct ListNode));
rehead=(struct ListNode *)malloc(sizeof(struct ListNode));
int i=0,n=0;
rehead=NULL;
p->next=NULL;
tmp->next=NULL;
p=head;
while(p)
{
p=p->next;
i++;
}
p=head;
while(p&&n<i/2)
{
tmp=p->next;
p->next=rehead;
rehead=p;
p=tmp;
n++;
}
if(i%2)
head=p->next;
else
head=p;
while(head&&rehead)
{
if(head->val!=rehead->val)
break;
head=head->next;
rehead=rehead->next;
}
if(head)
return false;
else
return true;
}
237.删除链表中的节点
void deleteNode(struct ListNode* node) {
node->val = node->next->val;
node->next=node->next->next;
}
876.链表的中间节点
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode* middleNode(struct ListNode* head){
struct ListNode *p;
int i=0,n=1;
p=head;
while(p)
{
p=p->next;
i++;
}
while(n<i/2+1)
{
head=head->next;
n++;
}
return head;
}
1290.二进制链表转整数
#include<math.h>
int getDecimalValue(struct ListNode* head){
int i=0,num=0;
struct ListNode *p;
p=(struct ListNode *)malloc(sizeof(struct ListNode));
p=head;
while(p)
{
p=p->next;
i++;
}
p=head;
while(p)
{
num += p->val*pow(2,(i-1));
p=p->next;
i--;
}
return num;
}
get flag
1.什么时候需要malloc?
(1)char * p = (char *)malloc(sizeof(char));
p = "xxxxxx";
第一句临时申请1个char空间,p是这个空间的地址,
但第二句就被赋值为字符串的地址。
则malloc得到的地址丢失了,无法free,导致内存泄漏。
内存泄漏:已动态分配的堆内存 未释放 或 无法释放
(2)临时需要一块内存,这块内存用来存储n个int的变量。
就需要使用malloc为pMax分配一块内存。可以这样做:
pMax = malloc(sizeof(int) * n);
if (pMax == NULL) // 错误处理 { TODO...}
memset(pMax, 0 , sizeof(int) * n);
这样我们就为pMax分配了一块内存大小为sizeof(int) *n 字节的内存。
这里malloc返回一个指向这块内存的首地址并将它赋给了int型指针变量pMax.
初始化后,就可以像数组一样操作这块int型的内存了
pMax[0]~pMax[n]都可指向整型变量
2.野指针
char *p="abc"; char *q; strcpy(q,p);
q是野指针,它的值是随机的内存地址,如果该地址的值接下来被直接覆盖,就可能有严重后果。
避免野指针的方法:
char *q=NULL;
意思是不指向任何内存地址
q=(char *)malloc(sizeof(char));
malloc给指针分配的内存是没有被其他程序使用的
综上,假如对于一个链表节点p,没有对p进行malloc,
直接p->next=NULL会在leetcode报错(devc会运行很长时间),
这里p->next就可能是随机内存中的值。
3.单链表建表
头插法建表:
新结点s插入到当前链表的表头结点L之后,就是在一个间隙中不断插节点
s->next=L->next; L->next=s;
尾插法建表:
增加一个尾指针r,将新节点插到当前单链表的表尾上
r->next=s; r=s;