链表问题:
虚拟节点:dummy
:避免讨论头结点为空。与head一样,在后面的步骤中一般不对其操作。
我的链表方向是从左到右。
curNode
:主要是用来遍历
nextNode
:curNode
的左边一个节点,是实现任务的主要变量,与preHead
配合使用
preHead
:curNode
的右边一个节点
LeetCode:209移除元素链表
思路:这一题还是很简单的。
关键点:分清楚几个辅助的节点的功能。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
//cpp
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* curNode = head;
ListNode* nextNode = dummy;
while(curNode != NULL){
if(curNode->val == val){
nextNode->next = curNode->next;
}
else{
nextNode = nextNode->next;
}
curNode = curNode->next;
}
return dummy->next;
}
};
//java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode pre = dummy;
ListNode cur = head;
while(cur != null){
if(cur.val == val){
pre.next = cur.next;
}
else{
pre =pre.next;
}
cur = cur.next;
}
return dummy.next;
}
}
LeetCode:707:设计链表
几乎是看着代码随想录做完的,后面需要再刷。
首先要构造出一个基本的链表节点的数据结构。
struct linkedNode{
int val;
linkedNode* next;
linkedNode(int val):val(val), next(nullptr){} // 构造函数
};
-
定义结构:
struct linkedNode{
这是一个叫做
linkedNode
的结构体的定义。在C++中,结构体(struct
)可以被用来定义一个数据结构,它可以包含多个数据成员。 -
数据成员:
int val; linkedNode *next;
这个结构体有两个数据成员:
val
:一个整数,用来存储链表节点的值。next
:一个指向linkedNode
类型的指针,用来指向下一个节点。
-
构造函数:
linkedNode(int val):val(val), next(nullptr){}
这是一个构造函数,它用于创建
linkedNode
类型的对象。linkedNode(int val)
:这是一个带有一个整数参数的构造函数。当你创建一个linkedNode
对象并传递一个整数时,这个构造函数会被调用。:val(val), next(nullptr)
:这是构造函数的初始化列表。在构造函数的主体执行之前,初始化列表用于初始化数据成员。val(val)
:这里的val(val)
意味着将传入的参数val
赋值给数据成员val
。注意,参数名和数据成员名是一样的,但它们是不同的变量。为了区分它们,你可以使用this->val
来引用数据成员。next(nullptr)
:这将next
指针初始化为nullptr
,表示它没有指向任何节点。
{}
:这是构造函数的主体。在这个特定的例子中,它是空的,因为所有的初始化都已经在初始化列表中完成了。
注意事项:
- 当数据成员名和构造函数参数名相同时,使用
this->
可以帮助区分它们。但在初始化列表中,编译器可以自动区分它们,所以this->
不是必需的。 - 初始化列表在构造函数主体之前执行。它是一个有效的方法来初始化数据成员,特别是当有默认值或基于其他数据成员的值时。
class MyLinkedList {
public:
struct linkedNode{
int val;
linkedNode* next;
linkedNode(int val):val(val), next(nullptr){} // 构造函数
};
MyLinkedList() { // 创建一个虚拟节点作为头结点
_dummyHead = new linkedNode(0);
_size = 0;
}
int get(int index) {
if(index > _size - 1)
return -1;
linkedNode* cur = _dummyHead->next;
while(index--){
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
linkedNode* newNode = new linkedNode(val);
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
_size++;
}
void addAtTail(int val) {
linkedNode* newNode =new linkedNode(val);
linkedNode* curNode = _dummyHead;
while(curNode->next != nullptr){
curNode = curNode->next;
}
curNode->next = newNode;
_size++;
}
void addAtIndex(int index, int val) {
if(index > _size){
return;
}
if(index < 0){
index = 0;
}
linkedNode* newNode = new linkedNode(val);
linkedNode* curNode = _dummyHead;
for(int i=0;i<index;i++){
curNode = curNode->next;
}
newNode->next = curNode->next;
curNode->next = newNode;
_size++;
}
void deleteAtIndex(int index) {
linkedNode* curNode = _dummyHead;
if(index >= _size || index < 0){
return;
}
while(index--){
curNode = curNode->next;
}
linkedNode* temp = curNode->next;
curNode->next = curNode->next->next;
delete temp; // 注意在C/C++中分别要用malloc/new 对应的free/delete 来删除不用的指针,并将这款指针指向空。
temp=nullptr;
_size--;
}
void printLinkedList() {
linkedNode* cur = _dummyHead;
while (cur->next != nullptr) {
cout << cur->next->val << " ";
cur = cur->next;
}
cout << endl;
}
private:
int _size;
linkedNode* _dummyHead;
};
/**
* 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);
*/
// 这道题目:要对基础的数据结构、对象的构造、
class listNode{
int val;
listNode next;
listNode(){};
listNode(int val){
this.val = val;
}
}
class MyLinkedList {
int size;
listNode head;
public MyLinkedList() {
// 初始化的时候不知道具体的长度size和head里面的数值,所以默认为空(0);
size = 0;
head =new listNode(0);
}
public int get(int index) {
listNode cur = head;
if(index <0||index>size-1){
return -1;
}
for(int i=0;i<=index;i++){
cur = cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
addAtIndex(0, val);
}
public void addAtTail(int val) {
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if(index > size){// 根据条件进行的设定
return;
}
if(index < 0){ // 根据条件进行的设定
index = 0;
}
size++; // 注意这里要将总长度加一
listNode cur = head;
for(int i=0;i<index;i++){
cur = cur.next;
}
listNode insert = new listNode(val);
insert.next = cur.next;
cur.next = insert;
}
public void deleteAtIndex(int index) {
if(index <0||index>size-1){
return;
}
size--;
if(index == 0){
// 注意因为这里都是返回的head所以对于删除第一个的情况要对head单独处理,不然还是返回之前的。
head =head.next;
return;
}
listNode cur =head;
for(int i=0;i<index;i++){
cur = cur.next;
}
cur.next = cur.next.next;
}
}
/**
* 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);
*/
LeetCode:206:翻转链表
这是一道门槛题。
**思路:**有点类似双指针。就是要注意三个量preNode,curNode,nextNode
。
关键点:
curNode
:主要是用来遍历
nextNode
:curNode
的左边一个节点,是实现任务的主要变量,与preHead
配合使用
preHead
:curNode
的右边一个节点.
**注意:**这里没有虚拟头结点。因为,反转之后会将虚拟头结点作为最后一个节点导致出错。直接将nextNode设置为NULL即可。
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
lass Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* curNode = head;
ListNode* nextNode = NULL;
ListNode* preNode = curNode;
while(curNode != NULL){
preNode = curNode->next;
curNode->next = nextNode;
nextNode = curNode;
curNode = preNode;
}
return nextNode;
}
};
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = null;
ListNode next = head;
while(cur != null){
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
递归方法 (关于递归的问题后需要补充加强)
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}