代码随想录训练营第三天| 203.移除链表元素、707.设计链表 、206.反转链表

文章介绍了如何在链表中移除指定元素,设计链表的基本操作,以及两种反转链表的方法。移除元素通过迭代找到首个不同节点,然后遍历删除目标值。设计链表包括添加、删除和查询元素。反转链表可以使用临时变量改变指针指向或递归实现。
摘要由CSDN通过智能技术生成

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.设计链表 (难度:中)

题目链接力扣
这个题就是实现链表的增删查功能块,我设计的是单链表,增设头节点对链表操作。
链表基本操作:
  1. MyLinkedList() 初始化 MyLinkedList 对象。
  2. int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
  3. void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
  4. void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
  5. void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
  6. 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.反转链表

题目链接力扣
题目描述:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表

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);
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值