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

想法:707题花费了一些时间,但是有收获。


203.移除链表元素203. 移除链表元素 - 力扣(LeetCode)

想法:做法大致分为两种,一种加虚拟头节点,另一种不加;之所以这样做的原因是当目标值是头节点时,对于删除头节点的处理方式。我所使用的是不加虚拟头节点,移动头节点方式。

其中需要注意的一点是 while (head != null && head.val == val) 语句要位于 if (head == null) 前面。原因是:假设一个链表中存放的值全是目标值,头节点需要一直后移,直到头节点为空,此时若 if (head == null) 语句在 while (head != null && head.val == val) 语句前面,则会出现,pre是null,而cur是null的下一个值,则会报错

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        // 特殊情况先处理
        // 若头节点出现目标值,删除头节点
        // 注意点while放在if前面
        while (head != null && head.val == val) {
            head = head.next;
        }
        if (head == null)
            return head;
        //注意:走完上面,到这里表明head中存储的值不是目标值,这就可以解释了为什么cur初始化为head.next
        ListNode pre = head;// 前一个
        ListNode cur = head.next;// 当前
        while (cur != null) {
            if (cur.val == val) {
                pre.next = cur.next;
            } else {
                pre = cur;//pre指向cur所在地
            }
            cur = cur.next;
        }
        return head;
    }
}

707.设计链表 707. 设计链表 - 力扣(LeetCode)

class MyLinkedList {
	int size;// 存储元素个数
	ListNode head;// 头节点

	// 初始化
	public MyLinkedList() {
		size = 0;
		head = new ListNode(0);
	}

	// 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
	public int get(int index) {
	if (index < 0 || index >= size) {
			return -1;
		}
		ListNode cur = head;
		while (index >= 0) {
			cur = cur.next;
			index--;
		}
		return cur.val;
	}

	// 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
	public void addAtHead(int val) {
		addAtIndex(0, val);
	}
// 在链表的最后插入一个节点,等价于在(末尾+1)个元素前添加
	public void addAtTail(int val) {
		addAtIndex(size, val);
	}

	// 在下标为 index节点之前插入一个新节点
	// 注意:index从零开始计数
	public void addAtIndex(int index, int val) {
		if (index > size) {// 大于链表长度
			return;
		}
		if (index < 0) {
			index = 0;
		}
		size++;// 为放入新的数据,提前增加一个长度
		ListNode t = head;
		for (int i = 0; i < index ; i++) {
			t = t.next;
		}
        ListNode insertNode = new ListNode(val);
		ListNode a = t.next;
		t.next = insertNode;
		insertNode.next = a;
	}
    // 删除链表中下标为 index 的节点。
	public void deleteAtIndex(int index) {
		if (index < 0 || index >= size) {
			return;
		}
	    size--;
        if (index == 0) {// 意思是删除头节点,做法头节点后移一位
			head = head.next;
			return;
		}
		ListNode deleteNode = head;
		for (int i = 0; i < index ; i++) {
			deleteNode = deleteNode.next;
		}
        deleteNode.next = deleteNode.next.next;
	}
}

206.反转链表206. 反转链表 - 力扣(LeetCode)

使用递归进行求解。

 //反转的关键
 //注意:这里的head.next指的是reverseList()函数中的那个元素,也就是当前元素的原先的下一个元素!!!很重要

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null)
            return head;

        ListNode newHead=reverseList(head.next);//使newHead指向最后一个节点
       
        head.next.next=head;
        head.next=null;
        
        return newHead;
    }
}

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我知道了。以下是对您的问题的回答: a. 动态分配内存的方法有很多,可以使用C语言的malloc函数,也可以使用C++中的new操作符,具体方法如下: C语言的malloc函数: ```c struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode)); ``` C++中的new操作符: ```c++ ListNode* node = new ListNode(); ``` b. 初始化单链表需要对链表节点的成员变量进行赋值,以下是一个示例: ```c++ struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; ListNode* head = NULL; ``` c. 头插法创建单链表的示例代码如下: ```c++ ListNode* head = new ListNode(); head->next = NULL; for (int i = 0; i < n; i++) { int x; cin >> x; ListNode* node = new ListNode(x); node->next = head->next; head->next = node; } ``` 尾插法创建单链表的示例代码如下: ```c++ ListNode* head = new ListNode(); head->next = NULL; ListNode* tail = head; for (int i = 0; i < n; i++) { int x; cin >> x; ListNode* node = new ListNode(x); node->next = NULL; tail->next = node; tail = node; } ``` d. 取链表某一位的值可以通过遍历链表来实现,以下是一个示例: ```c++ ListNode* p = head->next; int pos = 3; for (int i = 1; i < pos && p != NULL; i++) { p = p->next; } if (p == NULL) { cout << "链表长度不足" << endl; } else { cout << p->val << endl; } ``` e. 在链表的某一位进行插入操作可以通过遍历链表找到插入位置,然后插入一个新节点来实现,以下是一个示例: ```c++ ListNode* p = head; int pos = 3; for (int i = 1; i < pos && p != NULL; i++) { p = p->next; } if (p == NULL) { cout << "链表长度不足" << endl; } else { int x = 100; ListNode* node = new ListNode(x); node->next = p->next; p->next = node; } ``` f. 遍历链表可以通过循环遍历链表节点来实现,以下是一个示例: ```c++ ListNode* p = head->next; while (p != NULL) { cout << p->val << " "; p = p->next; } cout << endl; ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值