算法基础3:链表1

本文介绍了链表操作中的关键概念,如使用虚拟头节点进行统一遍历,以及如何移除、设计链表(包括添加、删除和反转)的方法。着重展示了LeetCode中的相关问题及其解题思路。
摘要由CSDN通过智能技术生成

链表类题目的思路

  1. 基本都需要一个虚拟头节点,来辅助完成对所有数据的统一遍历。
  2. 头节点也有可能为空,所以在判断时要将头节点的判断一并放入到整体判断中。

移除链表元素

题目链接:leetcode203

 ListNode* removeElements(ListNode* head, int val) {
    ListNode * dummyNode = new ListNode(0,head);
    ListNode * tmpNode = dummyNode;

    while(tmpNode->next!=nullptr){
        if(tmpNode->next->val == val){
            ListNode *Node = tmpNode->next;
            tmpNode->next = Node->next;
            delete Node;
        }
        else{
            tmpNode = tmpNode->next;
        }
    }
    head = dummyNode->next;
    delete dummyNode;

    return head;

}

思路

  1. 构建一个虚结点指向头节点,方便对后续做的所有操作统一。
  2. 需要注意的地方是,会不会读取空指针的next和val。
  3. 习惯将所有不需要的指针删除掉。

设计链表

题目链接:leetcode707

class MyLinkedList {

private:
    struct LinkedList{
        int val;
        LinkedList * next;
    };

    LinkedList *dummyNode;
    size_t linkLength;

public:
    MyLinkedList() {
        dummyNode = new LinkedList(0,nullptr);
        linkLength =0 ;

    }
    
    int get(int index) {
    	if(linkLength <= index) return -1;
        LinkedList *tmpNode = dummyNode;
        for(int i=0; i<index+1; ++i){
            if(tmpNode->next){
                tmpNode = tmpNode->next;
            } 
            else{
                return -1;
            }
        }

        return tmpNode->val;
    }
    
    void addAtHead(int val) {
        LinkedList *node = new LinkedList;
        node->val = val;
        node->next = dummyNode->next;
        dummyNode->next = node;
        linkLength++;
    }
    
    void addAtTail(int val) {
        LinkedList *tmpNode = dummyNode;
        while(tmpNode->next != nullptr){
            tmpNode = tmpNode->next;
        }
        LinkedList * newTail = new LinkedList(val, nullptr);
        tmpNode->next = newTail;
        linkLength++;
    }
    
    void addAtIndex(int index, int val) {
        if(index > linkLength){
            return;
        }
        LinkedList *tmpNode = dummyNode;
        for(int i=0; i<index; ++i){
            tmpNode = tmpNode->next;
        }
        LinkedList * newNode = new LinkedList(val,nullptr);
        newNode->next = tmpNode->next;
        tmpNode->next = newNode;
        linkLength++;
    }
    
    void deleteAtIndex(int index) {
        if(index >= linkLength){
            return;
        }
        LinkedList *tmpNode = dummyNode;
        for(int i=0; i<index; ++i){
            tmpNode = tmpNode->next;
        }
        LinkedList *deletenode = tmpNode->next;
        tmpNode->next = deletenode->next;
        delete deletenode;
        linkLength--;
    }
};

写代码过程中出现的问题

  1. MyLinkedList是基于每一个linkedList的单个结点构成一个整体的链表,所以首先应该有一个linkedlist的定义。
  2. 保存好链表的长度,可以帮助快速在插入和删除时判断位置是否合理。
  3. 存储一个虚拟头结点辅助对所有情况进行统一处理。
  4. 在遍历过程中,不能将遍历结点定义为dummyNode->next!!!如果链表为空的话,后续访问过程中,一访问就容易出现指针指向空地址的问题。

反转链表

题目链接:leetcode206

ListNode* reverseList(ListNode* head) {
    ListNode* dummyNode = new ListNode(0,head);
    ListNode* newList = new ListNode(0,nullptr);
    while(dummyNode->next != nullptr){
        ListNode *tmp = dummyNode->next;
        dummyNode->next = tmp->next;
        tmp->next = newList->next;
        newList->next = tmp;
    }
    return newList->next;
}

思路

  1. 原listnode结点每删除一个,就插在新列表的最前面一个即可。
  2. 边界情况,head为空,那么新列表的虚结点默认指向空,则不影响后续的判断。
  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值