代码随想录算法训练营第三天 | Leetcode203.移除链表元素、Leetcode707.设计链表、Leetcode206.反转链表

题目链接:203. 移除链表元素 - 力扣(LeetCode) 

        上学期的数据结构与算法有在学这些基本结构,一看到题目其实大概有个思路,但是因为代码能力不够强,对代码掌握不熟,过程还是有点坎坷的。要加油哦!!

思路:这里我只想说第二种方法:虚拟节点 其实它的本质就是将这个链表变成一个有头节点的链表,原来的头节点实际上就是首元节点。

代码复现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* removeElements(struct ListNode* head, int val){
        struct ListNode* newhead,*temp;
        newhead = malloc(struct ListNode*)(sizeof(struct ListNode);
        newhead = head;    //注意这里!!一定要记得赋值
        struct ListNode* cur = newhead;    //为什么不是head->next 是因为这是单链表的删除
        //开始在链表中查询比对删除
        while( cur->next!=NULL ){
            //如果下一个结点不是空结点并且所储存的元素的值是要删除的val值
            if( cur->next!=NULL && cur->val==val){
                //注意要删除的结点不是cur结点而是cur所指的下一结点
                temp = cur->next;
                cur->next = cur->next->next;
                free(temp);
                }
            //不用删除就直接后移继续查找后面的结点
            else{
            cur = cur->next;
            }
        }
        head = newhead->next;
        free(newhead);
        return head;
}
                

 其实最后也可以直接

return newhead->next;

但是做好空间管理占用内存会更少一点

题目链接:707. 设计链表 - 力扣(LeetCode)

        啊啊啊好麻烦一个题。。。好吧是我太垃的原因吗

注意:

  1. 删除链表最后一个元素时,就直接先遍历一边链表门将一个指针指向最后一个元素就好
  2. 插入元素时,先判断插入位置,如果是要插在第一个位置就调用头部插入的函数就好
  3. 删除元素时,一定也要分情况讨论,分删除第一个元素和其他元素
    void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
        MyLinkedList *p = obj->next,*temp;
        //如果要删除的是首元结点
        if( index == 0){
            temp = obj->next;
            if( temp!=NULL ){
                obj = obj->next;
                free(temp);
              }
        else{
            int i = 1;
            while( p!=NULL ){ 
                if(i == index){
                    //保留要删除的结点
                    temp = p->next;
                    //一定要判断该结点是否为空
                    if(temp != NULL){
                        p->next = temp->next;
                        free(temp);
                        }
                    }
                    else{
                        p = p->next;
                    }
                    i++;
                  }        
    }

题目链接:206. 反转链表 - 力扣(LeetCode)

        不难捏,但是我老是把一个简单的事情搞复杂

首先我是想一边遍历一边反转的,但是后来我又想把一个指针放在链表头部,一个指针放在链表尾部。然后弄不出,其实这样还需要在遍历一遍根本没必(这也是单链表的一个小缺点)。就用类似双指针的思想就好了。

双指针代码:

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode *slow,*fast,*temp;
    fast = head;
    slow = NULL;
    while(fast != NULL){
       temp = fast->next;    //保存原链表指向
       //反转链表指向
       fast->next = slow;
       //移动指针
       slow = fast;
       fast = temp;
    }
    return slow;
}

看到随想录上还有虚拟结点头插法和用栈解决的方法,想把第二题解决后再实现这两种方法。

头插法:可以认为利用原结点和头插法,建造一个新链表(不是全部真的新链表,只开辟了新的头结点)

代码复现:

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode *L = (struct ListNode*)malloc(sizeof(struct ListNode));
    L->next = NULL;
    struct ListNode *p,*q;
    p = head;
    while(p){
        //q保留p指针所指位置,否则待会反转链表被重新赋值后找不到,陷入死循环
        q = p-> next;
        p -> next = L->next;
        L -> next = p;
        //p返回原来链表
        p = q;
   }
   //注意不是return L;而是首元结点
   return L->next;
}

栈方法:

我试试学了C++或者Java之后能不能利用一些库函数和容器做。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值