算法第三天|203.移除链表元素,707.设计链表,206反转链表

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、移除链表元素(力扣203)

1. 力扣写法

2.自行创建链表并实现移除链表中元素的操作

二、设计链表(力扣707)

三、反转链表(力扣206)

1. 力扣写法

2.自行创建链表并实现链表反转的操


前言

提示:这里可以添加本文要记录的大概内容:

1.移除链表元素的算法

2.设计链表(插入,删除,查询)

3.反转链表


提示:以下是本篇文章正文内容,下面案例可供参考

一、移除链表元素(力扣203)

实现思想:在链表的头节点之前创建一个虚拟头节点(dummy_head),指针从虚拟头节点开始,每次判断指针的下一个值是否是需要删除的元素,如果是就执行p->next = p->next->next;否则就正常执行p = p->next操作

1. 力扣写法

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummy_head = new ListNode(-1);
        dummy_head->next = head;
        ListNode* cur = dummy_head;
        while(cur->next){
            if (cur->next->val == val){
                cur->next = cur->next->next;
            }
            else{
                cur = cur->next;
            }
        }
        return dummy_head->next;
    }
};

2.自行创建链表并实现移除链表中元素的操作

#include <iostream>

using namespace std;

struct ListNode{
	int val;
	ListNode* next;
	ListNode(int val):val(val), next(nullptr){}
};


//创建一个链表 
void create(ListNode* head){
	ListNode* p = head;
	for (int i = 5; i > 0; i--){ 
		ListNode* newNode = new ListNode(i);
		newNode->next = p->next;
		p->next = newNode;
	} 
}

//遍历整个链表,并输出每一个节点的值 
void printlist(ListNode* head){
	ListNode* p = head;
	while(p){
		cout << p->val << ' ';
		p = p->next;
	}
	cout << endl;
}

void remove_target(ListNode* &head, int target){
	//首先给链表添加一个虚拟头节点
	//原来的链表:0(head)->1->2->3->4->5->null
	//添加虚拟头节点后: 虚拟(dummy_head)->0(head)->1->2->3->4->5->null
	ListNode* dummy_head = new ListNode(-1);
	dummy_head->next = head;
	ListNode* p = dummy_head;
	while(p->next){
//		如果当前节点的下一个节点的值是我们要删除的值我们就删除下一个节点 
		if (p->next->val == target){
			p->next = p->next->next;
		}else{
		//否则就让p正常向后移动 
			p = p->next;
		}
	}
	//因为原本的头节点可能会被删除,所以在删除操作完成后要再次指定头节点 
	head = dummy_head->next;
	//释放虚拟头节点的空间 
	delete dummy_head;
}

int main(void){
	ListNode *head = new ListNode(0);
	//创建链表 
	create(head);
	//打印没有删除之前的链表 
	printlist(head);
	//删除指定值 
	remove_target(head, 1);
	//打印删除之后的链表 
	printlist(head);
	return 0;
} 

二、设计链表(力扣707)

1.力扣写法

class MyLinkedList {
public:
    struct LinkedNode{
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };

    //用来初始化链表
    MyLinkedList() {
        _dummy_head = new LinkedNode(-1);
        _dummy_head->next = nullptr;
        _size = 0;
    }
    
    int get(int index) {
        if (index < 0 || index > _size - 1){
            return -1;
        }
        LinkedNode* p = _dummy_head->next;
        while(index--) p = p->next;
        return p->val;
    }
    
    void addAtHead(int val) {
        LinkedNode* Node = new LinkedNode(val);
        Node->next = _dummy_head->next;
        _dummy_head->next = Node;
        _size++;
    }
    
    void addAtTail(int val) {
        LinkedNode* p = _dummy_head;
        while(p->next){
            p = p->next;
        }
        LinkedNode* Node = new LinkedNode(val);
        Node->next = p->next;
        p->next = Node;
        _size++;
    }
    
    void addAtIndex(int index, int val) {
        if (index < 0 || index > _size) return;
        LinkedNode* p = _dummy_head;
        while(index--){
            p = p->next;
        }
        LinkedNode* Node = new LinkedNode(val);
        Node->next = p->next;
        p->next = Node;
        _size++;
    }
    
    void deleteAtIndex(int index) {
        if (index < 0 || index > _size - 1) return;
        LinkedNode* p = _dummy_head;
        while(index--){
            p = p->next;
        }
        LinkedNode* tmp = p->next;
        p->next = tmp->next;
        delete tmp;
        _size--;
    }
    private:
        int _size;
        LinkedNode* _dummy_head;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

三、反转链表(力扣206)

实现思想:用三个指针pre, cur, tmp,pre从空开始,cur从头节点开始,tmp每次用来保存cur->next,因为如果不保存cur->next那么在执行cur->next = pre,操作之后cur指针后面的节点会全部丢失

1. 力扣写法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = head;
        ListNode* pre = nullptr;
        while(cur != nullptr){
            ListNode* tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
};

2.自行创建链表并实现链表反转的操作

#include <iostream>

using namespace std;

struct ListNode{
	int val;
	ListNode* next;
	ListNode(int val):val(val), next(nullptr){}
};


//创建一个链表 
void create(ListNode* head){
	ListNode* p = head;
	for (int i = 5; i > 0; i--){ 
		ListNode* newNode = new ListNode(i);
		newNode->next = p->next;
		p->next = newNode;
	} 
}

//遍历整个链表,并输出每一个节点的值 
void printlist(ListNode* head){
	ListNode* p = head;
	while(p){
		cout << p->val << ' ';
		p = p->next;
	}
	cout << endl;
}

//反转链表 
void reverse(ListNode* &head){
	ListNode* pre = nullptr;
	ListNode* cur = head;
	//while(cur)这种写法会让cur最后指向一个空指针,这时候pre指向的是整个链表最后一个节点,所以要把pre赋给head 
	
	//while(cur->next)这种写法会让指针停留在最后一个节点且不会将最后一个节点指向倒数第二个节点
	//因为最后一个节点的next指针指向null,因此不会进入最后一次循环,也就不会将最后一个节点指向
	//倒数第二个节点,链表也就丢失了一个节点 ,因此不能使用这种方式 
	while(cur){
		ListNode* tmp = cur->next;
		cur->next = pre;
		pre = cur;
		cur = tmp; 
	}
	head = pre;

} 

int main(void){
	ListNode *head = new ListNode(0);
	//创建链表 
	create(head);
	//打印没有删除之前的链表 
	printlist(head);
	//反转链表
	reverse(head);
	//打印反转之后的链表
	printlist(head); 
	return 0;
} 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值