leetcode203题(移除链表元素)
题目描述:
给你一个链表的头节点
head
和一个整数val
,请你删除链表中所有满足Node.val == val
的节点,并返回 新的头节点 。示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]示例 2:
输入:head = [], val = 1 输出:[]示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
解题思路:
解法一:
将第一个元素和其他元素分开操作。首先保证链表的第一个元素不是要删除的元素,因此要先进行while循环,条件为head!=NULL && head->val==val,头指针不能为空指针,如果头指针为空指针,则我们是在对一个空指针进行操作,编译出错。同理在下面的条件中,p->next和p都不能为空,因为下面的语句中要对他们进行操作。
struct ListNode* removeElements(struct ListNode* head, int val) {
while(head!=NULL && head->val==val){
head = head->next;
}
struct ListNode* p =head;
while(p!=NULL&&p->next!=NULL){
if(p->next->val==val){
p->next=p->next->next;
}
else{p=p->next;}
}
return head;
}
解法二:
在前面生成一个虚拟头节点,将所有元素统一处理。
struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode ListNode;
ListNode *shead;
shead = (ListNode *)malloc(sizeof(ListNode));
shead->next = head;
ListNode *cur = shead;
while(cur->next != NULL){
if (cur->next->val == val){
ListNode *tmp = cur->next;
cur->next = cur->next->next;
free(tmp);
}
else{
cur = cur->next;
}
}
head = shead->next;
free(shead);
return head;
}
注意点:
第一:编译过程中需要注意的是我们操作的指针不能为空
第二:在解法二中需要动态分配一个空间用来放生成的链表元素,且利用tmp去指向需要删除的链表元素,通过free释放malloc的空间,不然会造成内存泄漏。
leetcode707题(设计链表)
题目描述:
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:
val
和next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。如果是双向链表,则还需要属性
prev
以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。实现
MyLinkedList
类:
MyLinkedList()
初始化MyLinkedList
对象。int get(int index)
获取链表中下标为index
的节点的值。如果下标无效,则返回-1
。void addAtHead(int val)
将一个值为val
的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。void addAtTail(int val)
将一个值为val
的节点追加到链表中作为链表的最后一个元素。void addAtIndex(int index, int val)
将一个值为val
的节点插入到链表中下标为index
的节点之前。如果index
等于链表的长度,那么该节点会被追加到链表的末尾。如果index
比长度更大,该节点将 不会插入 到链表中。void deleteAtIndex(int index)
如果下标有效,则删除链表中下标为index
的节点。示例:
输入 ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"] [[], [1], [3], [1, 2], [1], [1], [1]] 输出 [null, null, null, null, 2, null, 3] 解释 MyLinkedList myLinkedList = new MyLinkedList(); myLinkedList.addAtHead(1); myLinkedList.addAtTail(3); myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3 myLinkedList.get(1); // 返回 2 myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3 myLinkedList.get(1); // 返回 3
解题思路:
typedef struct MyLinkedList{
int val;
struct MyLinkedList* next;
} MyLinkedList;
MyLinkedList* myLinkedListCreate() {
MyLinkedList* head = (MyLinkedList*) malloc(sizeof (MyLinkedList));
head ->next = NULL;
return head;
}
int myLinkedListGet(MyLinkedList* obj, int index) {
MyLinkedList *p= obj ->next;
for(int i=0;p != NULL;i++){
if (i == index){
return p->val;
}else{
p=p->next;
}
}
return -1;
}
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
MyLinkedList *nnode =(MyLinkedList*)malloc(sizeof(MyLinkedList));
nnode->val = val;
nnode->next = obj->next;
obj->next = nnode;
}
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList *nnode =(MyLinkedList*)malloc(sizeof(MyLinkedList));
nnode->val = val;
MyLinkedList *p = obj ;
while(p -> next != NULL){
p= p -> next;
}
nnode->next = p->next;
p->next = nnode;
}
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
MyLinkedList *nnode =(MyLinkedList*)malloc(sizeof(MyLinkedList));
nnode->val = val;
MyLinkedList *p = obj ;
for( int i=0;p != NULL;i++){
if (i == index){
nnode->next = p->next;
p->next = nnode;
}else{
p=p->next;
}
}
}
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
if (index == 0){
MyLinkedList *tmp = obj->next;
if (tmp != NULL){
obj->next = tmp->next;
free(tmp);
}
return;
}
MyLinkedList *cur = obj->next;
for (int i = 1 ;cur != NULL && cur->next != NULL; i++){
if (i == index){
MyLinkedList *tmp = cur->next;
if (tmp != NULL) {
cur->next = tmp->next;
free(tmp);
}
return;
}
else{
cur = cur->next;
}
}
}
void myLinkedListFree(MyLinkedList* obj) {
while(obj != NULL){
MyLinkedList *tmp = obj;
obj = obj->next;
free(tmp);
}
}
注意点:
在设计myLinkedListAddAtTail的时候,我将新建的临时指针p指向了虚拟头指针obj的下一个节点,但是当原本的链表为空时,即不存在真实的头指针,则不存在p->next,while循环中的条件不存在,编译错误,操作空指针了。