203.移除链表元素
本题的重点是创建一个虚拟头节点链接到表头,头节点的好处是可以让删除操作得到统一,还有一个细节是要及时处理释放节点的内存空间。
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) {}
};
ListNode* removeElements(ListNode* head, int val) {
ListNode *dummyhead = new ListNode(0);//虚拟头节点
dummyhead->next = head;
ListNode* p = dummyhead;//p指针遍历链表
while(p->next != nullptr){
if(p->next->val == val){
ListNode *temp = p->next;//临时指针,用于节点的释放
p->next = temp->next;
delete temp;
}
else{
p = p->next;
}
}
head = dummyhead->next;
delete dummyhead;
return head;
}
另外补充C++易错点,若访问结构体成员,对象是实例可以用.(点),若对象是指针只能用->访问。
707.设计链表
class MyLinkedList {
public:
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode(int val):val(val),next(nullptr){}
};
/*MyLinkedList() 初始化 MyLinkedList 对象。*/
MyLinkedList() {
_dummyhead = new LinkedNode(0);
_size = 0;
}
/*获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。*/
int get(int index) {
if(index < 0 || index > (_size - 1))
return -1;
LinkedNode* p = _dummyhead->next;
while(index--){
p = p->next;
}
return p->val;
}
//将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtHead(int val) {
LinkedNode* newNode = new LinkedNode(val);
newNode->next = _dummyhead->next;
_dummyhead->next = newNode;
_size++;
}
//将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtTail(int val) {
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyhead;//找到链表最后一个元素
while(cur->next != nullptr){
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;
}
/*将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
*/
void addAtIndex(int index, int val) {
if(index > _size){
return;
}
LinkedNode* p = _dummyhead;
while(index--){//找到相应下标的节点
p = p->next;
}
LinkedNode* newNode = new LinkedNode(val);
newNode->next = p->next;
p->next = newNode;
_size++;
}
//如果下标有效,则删除链表中下标为 index 的节点。
void deleteAtIndex(int index) {
if(index >= _size || index < 0){
return;
}
LinkedNode* cur = _dummyhead;
while(index--){
cur = cur->next;
}
LinkedNode* temp = cur->next;
cur->next = cur->next->next;
delete temp;
_size--;
}
private:
int _size;
LinkedNode* _dummyhead;
};
206.反转链表
解1(双指针法):思路如图解,将两两节点的关系反转即可。时间复杂度O(n),空间复杂度O(1)
ListNode* reverseList(ListNode* head) {
ListNode* cur = head;//1
ListNode* pre = nullptr;
ListNode* temp;//保存cur下一个节点,移接关系可以找到cur的后一个节点
while(cur){
temp = cur->next;//2,先保存cur后一个节点
cur->next = pre;//3
//更新pre和cur指针
pre = cur;//更新顺序不能反
cur = temp;
}
head = pre;
return head;
}
解2(递归法):
和双指针法思路是相同的,把代码相应的更改赋值即可。
ListNode* reverse(ListNode* pre,ListNode* cur){
if(!cur)//终止条件
return pre;
ListNode* temp = cur->next;//保存cur后一个节点
cur->next = pre;//反转
return reverse(cur,temp);//更新pre和cur指针,若到最后一个节点会满足第一个if,然后返回pre到上一层函数....
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr,head);//()内初始化pre和cur值
}