链表类题目的思路
- 基本都需要一个虚拟头节点,来辅助完成对所有数据的统一遍历。
- 头节点也有可能为空,所以在判断时要将头节点的判断一并放入到整体判断中。
移除链表元素
题目链接:leetcode203
ListNode* removeElements(ListNode* head, int val) {
ListNode * dummyNode = new ListNode(0,head);
ListNode * tmpNode = dummyNode;
while(tmpNode->next!=nullptr){
if(tmpNode->next->val == val){
ListNode *Node = tmpNode->next;
tmpNode->next = Node->next;
delete Node;
}
else{
tmpNode = tmpNode->next;
}
}
head = dummyNode->next;
delete dummyNode;
return head;
}
思路
- 构建一个虚结点指向头节点,方便对后续做的所有操作统一。
- 需要注意的地方是,会不会读取空指针的next和val。
- 习惯将所有不需要的指针删除掉。
设计链表
题目链接:leetcode707
class MyLinkedList {
private:
struct LinkedList{
int val;
LinkedList * next;
};
LinkedList *dummyNode;
size_t linkLength;
public:
MyLinkedList() {
dummyNode = new LinkedList(0,nullptr);
linkLength =0 ;
}
int get(int index) {
if(linkLength <= index) return -1;
LinkedList *tmpNode = dummyNode;
for(int i=0; i<index+1; ++i){
if(tmpNode->next){
tmpNode = tmpNode->next;
}
else{
return -1;
}
}
return tmpNode->val;
}
void addAtHead(int val) {
LinkedList *node = new LinkedList;
node->val = val;
node->next = dummyNode->next;
dummyNode->next = node;
linkLength++;
}
void addAtTail(int val) {
LinkedList *tmpNode = dummyNode;
while(tmpNode->next != nullptr){
tmpNode = tmpNode->next;
}
LinkedList * newTail = new LinkedList(val, nullptr);
tmpNode->next = newTail;
linkLength++;
}
void addAtIndex(int index, int val) {
if(index > linkLength){
return;
}
LinkedList *tmpNode = dummyNode;
for(int i=0; i<index; ++i){
tmpNode = tmpNode->next;
}
LinkedList * newNode = new LinkedList(val,nullptr);
newNode->next = tmpNode->next;
tmpNode->next = newNode;
linkLength++;
}
void deleteAtIndex(int index) {
if(index >= linkLength){
return;
}
LinkedList *tmpNode = dummyNode;
for(int i=0; i<index; ++i){
tmpNode = tmpNode->next;
}
LinkedList *deletenode = tmpNode->next;
tmpNode->next = deletenode->next;
delete deletenode;
linkLength--;
}
};
写代码过程中出现的问题
- MyLinkedList是基于每一个linkedList的单个结点构成一个整体的链表,所以首先应该有一个linkedlist的定义。
- 保存好链表的长度,可以帮助快速在插入和删除时判断位置是否合理。
- 存储一个虚拟头结点辅助对所有情况进行统一处理。
- 在遍历过程中,不能将遍历结点定义为dummyNode->next!!!如果链表为空的话,后续访问过程中,一访问就容易出现指针指向空地址的问题。
反转链表
题目链接:leetcode206
ListNode* reverseList(ListNode* head) {
ListNode* dummyNode = new ListNode(0,head);
ListNode* newList = new ListNode(0,nullptr);
while(dummyNode->next != nullptr){
ListNode *tmp = dummyNode->next;
dummyNode->next = tmp->next;
tmp->next = newList->next;
newList->next = tmp;
}
return newList->next;
}
思路
- 原listnode结点每删除一个,就插在新列表的最前面一个即可。
- 边界情况,head为空,那么新列表的虚结点默认指向空,则不影响后续的判断。