本题有两种解法:
方法一:直接再原来的基础上进行链表的删除。
1.C语言版:
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode *tmp; //创建一个新的指针
while(head != NULL && head -> val == val){
tmp = head;
head = head->next;
free(tmp);
}
struct ListNode *cur = head;
while(cur != NULL && (tmp = cur->next) != NULL){
if (tmp->val == val) {
cur ->next = cur ->next ->next;
free(tmp);
}else{
cur =cur->next;
}
}
return head;
思路:该方法主要是再原来的链表的基础上来进行操作,因为头结点的与其他结点的删除不同,头结点没有前一个结点,所以需要单独分离出来。头结点之后的结点的移除只需要创建新的指针,将它跳过后释放即可。
头结点的移除过程具体如下图所示:
2.Java版本
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val) {
head = head.next;
}
// 已经为null,提前退出
if (head == null) {
return head;
}
// 已确定当前head.val != val
ListNode pre = head;
ListNode cur = head.next;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return head;
}
方法二:设置一个虚拟的头结点来对应。
1.C语言版
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode *dummy; //创建一个虚拟的头结点
dummy =(struct ListNode*)malloc(sizeof(struct ListNode)); //创建这个虚拟的结点
dummy ->next =head;
struct ListNode *cur;
cur = dummy; //从虚拟的头结点开始是因为删除一个结点的话,需要的是它的前一个结点,直接指向后面的结点。
while(cur->next != NULL){
if (cur->next->val == val){ //判断他的下一个结点是否是题目中所求的结点
struct ListNode *tmp = cur->next; //需要一个临时的指针指向cur的下一个结点中去
cur->next = cur->next->next;
free(tmp);
}
else{
cur = cur->next;
}
}
head = dummy->next; //释放虚拟的结点
free(dummy);
return head;
}
思路:该方法主要创建一个新的虚拟的头结点,使该链表变为一个有头结点的链表,之后再在其基础上来进行操作。
2.Java版本
public ListNode removeElements(ListNode head, int val) {
if (head == null) {
return head;
}
// 因为删除可能涉及到头节点,所以设置dummy节点,统一操作
ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy;
ListNode cur = head;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return dummy.next;
}
Java版本的数据结构使用方法,及其相关的描述可借鉴:链接