203.移除链表元素 (题目链接:力扣)
思路:遍历一遍链表元素,删除相同值的元素,唯一要注意的就是头结点和非头结点的删除方式有些区别,由此衍生出一下两种方法,第一种方法把头结点区别开来,第二种方法引入一个虚拟的头结点,剩余的节点就可以统一对待了。
ListNode* removeElements(ListNode* head, int val){
while(head != NULL && head->val == val){
head = head->next;
}
ListNode* cur = head;
while(cur != NULL && cur->next != NULL){
if(cur->next->val == val){
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}else{
cur = cur->next;
}
}
return head;
}
第二种方法:
ListNode* removeElements(ListNode* head, int val){
ListNode* newHead = new ListNode();
newHead->next = head;
ListNode* cur = newHead;
while(cur != NULL && cur->next != NULL){
if(cur->next->val == val){
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}else{
cur = cur->next;
}
}
head = newHead->next;
delete newHead;
return newHead->next;
}
707.设计链表(题目链接:力扣)
思路:单链表就很简单,就没考虑用双链表做了,无非就是增删改查这几种链表的常用方法,也可以看作是复习一下c++里面的类的成员变量创建了。
class MyLinkedList
{
public:
struct LinkedNode
{
int val;
LinkedNode *next;
LinkedNode(int x) : val(x), next(NULL) {}
};
MyLinkedList()
{
size = 0;
head = new LinkedNode(0);
}
int get(int index)
{
if (index >= size || size < 0)
{
return -1;
}
LinkedNode *tmpHead = head;
while (index-- > 0)
{
tmpHead = tmpHead->next;
}
return tmpHead->next->val;
}
void addAtHead(int val)
{
LinkedNode* tmp = new LinkedNode(val);
tmp->next = head->next;
head->next = tmp;
size++;
}
void addAtTail(int val)
{
LinkedNode* tmp = new LinkedNode(val);
LinkedNode *tmpHead = head;
while (tmpHead->next != NULL)
{
tmpHead = tmpHead->next;
}
tmpHead->next = tmp;
size++;
}
void addAtIndex(int index, int val)
{
if (index > size)
{
return;
}
LinkedNode *tmpHead = head;
while (index-- > 0)
{
tmpHead = tmpHead->next;
}
LinkedNode* tmp = new LinkedNode(val);
tmp->next = tmpHead->next;
tmpHead->next = tmp;
size++;
}
void deleteAtIndex(int index)
{
if (index >= size)
{
return;
}
LinkedNode *tmpHead = head;
while (index-- > 0)
{
tmpHead = tmpHead->next;
}
LinkedNode *tmp = tmpHead->next;
tmpHead->next = tmpHead->next->next;
delete tmp;
size--;
}
private:
int size;
LinkedNode *head;
};
206.反转链表 (题目链接:力扣)
思路:首先想到的是用递归的方法,先找到链表的最后一个元素,然后逐步创建新节点往回便利,后来看了卡哥的方法想起来可以不用创建新节点,直接在原来的链表上修改指针就好了(虽然短暂形成了指针环,但是立马又解开了)。
ListNode* reverseList(ListNode* head){
if(head == NULL || head->next == NULL){
return head;
}
ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
第二种也是看了卡哥的解析才知道的双指针的做法(不得不感叹双指针做法真是万金油!),严格来说其实用到了三根指针,从前往后遍历,每次反转前面的指针时,都要留一根指针在后面做好准备,不然链表断开就找不到了。
ListNode* reverseList(ListNode* head){
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* tmp;
while(cur != NULL){
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
其实这种方法也能写成递归,但我感觉那样就有点刻意用递归了,不如这样简单好理解,感兴趣的小伙伴可以试一下。