前言
LeetCode题目:203、707、206
Takeaway:全都是链表的基础知识,难点在边界的处理,尤其是707的双链表实现,要判断的边界非常多。206有递归实现。
一、LeetCode 203
没什么好说的,很基础的链表题,没有算法,只有基础知识。
/**
* 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) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* p = head;
while(p!=NULL && p->val == val){
head = p->next;
p = head;
}
p = head;
while(p!=NULL && p->next!=NULL){
while(p->next!=NULL && p->next->val == val){
p->next = p->next->next;
}
p = p->next;
}
return head;
}
};
二、LeetCode 707
同203,没有什么算法,全是考验基本功和边界处理,此为单链表实现,双链表边界更多。
class MyLinkedList {
public:
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode(int val):val(val), next(nullptr){}
};
MyLinkedList() {
_size = 0;
_dummyHead = new LinkedNode(0);
}
int get(int index) {
if(index > _size-1)
return -1;
LinkedNode* cur_ptr = _dummyHead;
int cur_num = 0;
while(cur_num <= index){
cur_ptr = cur_ptr->next;
cur_num++;
}
return cur_ptr->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* cur_ptr = _dummyHead;
int cur_num = 0;
while(cur_num < _size){
cur_ptr = cur_ptr->next;
cur_num++;
}
cur_ptr->next = newNode;
_size++;
}
void addAtIndex(int index, int val) {
LinkedNode* newNode = new LinkedNode(val);
/* 新的元素可以放在末尾,此时index == _size */
if(index > _size)
return;
LinkedNode* cur_ptr = _dummyHead;
int cur_num = 0;
while(cur_num < index){
cur_ptr = cur_ptr->next;
cur_num++;
}
newNode->next = cur_ptr->next;
cur_ptr->next = newNode;
_size++;
}
void deleteAtIndex(int index) {
if(index >= _size)
return;
LinkedNode* cur_ptr = _dummyHead;
int cur_num = 0;
while(cur_num < index){
cur_ptr = cur_ptr->next;
cur_num++;
}
cur_ptr->next = cur_ptr->next->next;
_size--;
}
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);
*/
三、LeetCode 206
双指针就可以解决问题,还写了递归实现,注意需要返回值来保存最后一个指针(新链表的头指针)。
1、双指针
/**
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == nullptr || head->next == nullptr){
return head;
}
ListNode* new_head = new ListNode();
new_head->val = head->val;
ListNode* cur = new_head;
while(head != nullptr && (head->next != nullptr)){
head = head->next;
ListNode* new_node = new ListNode();
new_node->val = head->val;
new_node->next = cur;
cur = new_node;
}
return cur;
}
};
2、递归
设计递归出口,每层递归要做的事,最后再考虑参数和返回值。
/**
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
return reverse(NULL, head);
}
ListNode* reverse(ListNode* pre, ListNode* cur){
if(cur == NULL){
return pre;
}
ListNode* ans = reverse(cur, cur->next);
cur->next = pre;
return ans;
}
};
总结
今天的题仍然没有什么难度,考验的主要还是基本功,让我回忆起了链表的操作方法和C++类的定义还有递归的设计逻辑。