203.移除链表元素
题目链接:力扣
题目描述:给你一个链表的头节点head
和一个整数val
,请你删除链表中所有满足Node.val == val
的节点,并返回 新的头节点 。
示例:输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
输入:head = [7,7,7,7], val = 7
输出:[]
先使头节点指向第一个与目标值不相同的节点。
struct ListNode* removeElements(struct ListNode* head, int val){
//使头节点指向第一个与目标值不同的节点
while(head&&head->val==val){
head=head->next;
}
struct ListNode* p=(struct ListNode*)malloc(sizeof(struct ListNode));
p=head; //p指针标识节点,不改变head位置以便返回头节点
while(p->next){
while(p->next&&(p->next)->val==val){ //仍然需要约束p->next
p->next=p->next->next; //跳过与目标值相同的节点
}
p=p->next;
}
return head;
}
对于head=[1,1,2,2,2,2,1],val=2这样的示例,正确结果是返回[1,1,1],因此双层循环中的第二层不能用if判断来代替循环。
并且由于第二层循环中的p一直在变动,第一层的判断条件已经不能约束当前的p->next是否为NULL,因此仍然需要判断条件p->next。
707.设计链表 (难度:中)
题目链接:
力扣
这个题就是实现链表的增删查功能块,我设计的是单链表,增设头节点对链表操作。
链表基本操作:
- MyLinkedList() 初始化 MyLinkedList 对象。
- int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
- void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
- void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
- void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
- void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
//定义结构体
typedef struct LNode{
int val;
struct LNode *next;
} MyLinkedList;
//初始化
MyLinkedList* myLinkedListCreate() {
MyLinkedList *obj; //obj是头节点
obj=(MyLinkedList*)malloc(sizeof(MyLinkedList));
obj->next=NULL;
return obj;
}
//获取链表中下标为 index 的节点的值。如果下标无效,则返回-1
int myLinkedListGet(MyLinkedList* obj, int index) {
if(index<0) return -1; //下标小于0直接返回-1
MyLinkedList *p=obj->next;
int i=0;
while(p){
if(i++==index){
return p->val;
}
p=p->next;
}
return -1;
}
//将值为val的节点头插法插入链表
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
MyLinkedList *p=(MyLinkedList*)malloc(sizeof(MyLinkedList));
p->val=val;
p->next=obj->next;
obj->next=p; //把节点挂到头节点之后
}
//将值为val的节点尾插法插入链表
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList *t=obj;
//追踪到尾节点
while(t->next){
t=t->next;
}
MyLinkedList *p=(MyLinkedList*)malloc(sizeof(MyLinkedList));
p->val=val;
p->next=NULL;
t->next=p; //追加节点
}
//将一个值为 val 的节点插入到链表中下标为 index 的节点之前
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
MyLinkedList *p=(MyLinkedList*)malloc(sizeof(MyLinkedList));
p->val=val;
p->next=NULL;
MyLinkedList *t=obj;
int i=-1; //初始位置在头节点,不算在下标内,记为-1
while(t){ //当前节点不为空就可以进行比较
if(i++==index-1){
p->next=t->next;
t->next=p;
break;
}
t=t->next;
}
}
这里要注意循环条件
//删除链表中下标为 index 的节点
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
MyLinkedList *t=obj;
int i=-1;
//由于要用到t->next->next,必须确保t->next存在
while(t&&t->next){
if(i++==index-1){
t->next=t->next->next;
}
t=t->next;
}
}
//清空链表
void myLinkedListFree(MyLinkedList* obj) {
//依次free
while(obj){
MyLinkedList* t=obj;
obj=obj->next;
free(t);
}
}
206.反转链表
1.用临时变量改变指针指向
个人感觉像用三个指针实现类似双链表,既知道前一个结点也知道下一个结点。
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* pre=NULL;
struct ListNode* cur=head;
while(cur){
struct ListNode* temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
return pre;
}
2.递归
根据上面代码写,这个我真不会,我把这个题背下来算了
struct ListNode* reverse(struct ListNode* pre,struct ListNode* cur){
if(cur==NULL) return pre;
struct ListNode* temp=cur->next;
cur->next=pre;
return reverse(cur,temp);
}
struct ListNode* reverseList(struct ListNode* head){
return reverse(NULL,head);
}