思路:设计一个虚拟头结点L,方便我们进行操作,其指针域指向首元节点,设置结点指针变量tmp,根据题目条件删除符合要求的结点,链表方便我们进行修改和删除结点,最后返回值要注意返回的是L->next,因为我们的修改指针都是基于L实现的,返回head会导致出现一些错误,因为我们并没有释放这些存储空间,head指向位置依旧存储信息,所以我们要返回L->next。
时间复杂度:O(n)
空间复杂度:O(1)
来看下非递归代码
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* L = malloc(sizeof(struct ListNode));//设置头节点
L->next = head;//指针域指向首元节点
struct ListNode* tmp = L;
while(tmp->next!=NULL){
if(tmp->next->val==val){
tmp->next = tmp->next->next;
}
else{
tmp = tmp->next;
}
}
return L->next;
}
再看下递归写法代码
struct ListNode* removeElements(struct ListNode* head, int val){
if(head == NULL){
return NULL;
}
head->next = removeElements(head->next, val);
return head->val == val? head->next:head;
}
思路:在这里我们实现的是单向非循环链表,设置头结点方便操作统一,所有的操作都是基于此实现的,代码段和注释如下。
//链表结点结构体定义
typedef struct {
int val;
struct MyLinkedList* next;
} MyLinkedList;
//创建链表,返回链表头指针
MyLinkedList* myLinkedListCreate() {
MyLinkedList* L = (MyLinkedList*)malloc(sizeof(MyLinkedList));
if(!L){
return NULL;
}
L->next = NULL;
return L;
}
//找到指定index的元素结点值
int myLinkedListGet(MyLinkedList* obj, int index) {
int val = -1;
int j = 0;
MyLinkedList* p = obj->next;
while(p != NULL && j < index){
p = p->next;
j++;
}
if(p){
val = p->val;
return val;
}
else{
return val;
}
}
//头插法插入结点
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
MyLinkedList* pnew = (MyLinkedList*)malloc(sizeof(MyLinkedList));
pnew->val = val;
pnew->next = obj->next;
obj->next = pnew;
return;
}
//尾插法插入结点
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList* pnew = (MyLinkedList*)malloc(sizeof(MyLinkedList));
pnew->val = val;
MyLinkedList* p = obj;
while(p->next != NULL){
p = p->next;
}
p->next = pnew;
pnew->next = NULL;
return;
}
//在指定下标结点前增添结点
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
if (index <= 0){
//下标小于零,相当于头插法插入结点
//直接调用函数
myLinkedListAddAtHead(obj, val);
return;
}
int j = 1;
MyLinkedList* pnew = (MyLinkedList*)malloc(sizeof(MyLinkedList));
MyLinkedList* p = obj;
while(p->next && j < index){
p = p->next;
j++;
}
if(p->next != NULL){
p = p->next;
pnew->next = p->next;
pnew->val = val;
p->next = pnew;
return;
}
else{
return;
}
}
//删除指定下标的元素
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;
MyLinkedList* del = obj->next;
int j = 0;
while(j < index-1 && cur != NULL){
j++;
cur = cur->next;
del = del->next;
}
if(del != NULL && del->next != NULL){
del = del->next;
cur->next = del->next;
free(del);
}
return;
}
//释放链表
void myLinkedListFree(MyLinkedList* obj) {
while(obj!=NULL){
MyLinkedList* tmp = obj;
obj = obj->next;
free(tmp);
}
}
思路:利用两个指针,不断修改链表结点的指针域即可,最后将head指针域置为空指针,返回最后一个结点位置即可。
非递归:
时间复杂度:O(n)
空间复杂度:O(1)
递归:
时间复杂度:O(n)
空间复杂度:O(n)
看下非递归解法代码
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* L = (struct ListNode*)malloc(sizeof(struct ListNode));
L->next = head;
struct ListNode* pl = L;
struct ListNode* pr = L->next;
struct ListNode* tmp = NULL;
if(!head){
return NULL;
}
while(pr){
tmp = pr->next;
pr->next = pl;
pl = pr;
pr = tmp;
}
head->next = NULL;
return pl;
}
递归解法代码
struct ListNode* reverseList(struct ListNode* head) {
if (head == NULL || head->next == NULL) {
return head;
}
struct ListNode* ntail = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return ntail;
}