定位节点,修改引用,注意头结点和空节点
class Solution:
def deleteNode(self, head:ListNode, val: int):
if head.val val:
return head.next
pre, cur = head, head.next
while cur and cur.val != val:
pre, cur = cur, cur.next
if cur:
pre.next = cur.next
return head
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var deleteNode = function(head, val) {
if (head === null || head.val === val) {
head = head.next
}
let pre = head
let current = head.next
while (current) {
if (current.val === val) {
pre.next = current.next
break
}
pre = current
current = current.next
}
return head
};
#python解题思路
class Solution(object):
def deleteNode(self, head, val):
“””
:type head: ListNode
:type val: int
:rtype: ListNode
“””
if not head:
return ‘Error’
if head.val == val:
return head.next
pre, cur = head, head.next
while cur and cur.val != val:
pre, cur = cur, cur.next
if cur:
pre.next = cur.next
return head
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
dummy = ListNode(0) #初始设置一个伪结点dummy
dummy.next = head
# 若头结点就是要删除的点,则直接返回头结点后面的点
if head.val val:
return head.next
while head and head.next:
#若头结点后面的点是要删除的点,则将要删除点后面一位的值赋给要删除点,这样就将要删除点给删除了
if head.next.val val:
head.next = head.next.next
head = head.next
return dummy.next
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def deleteNode(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
# 先判断头节点
if head.val == val:
return head.next
cur = head
while cur.next:
if cur.next.val == val:
cur.next = cur.next.next
return head
cur = cur.next
return head
时间复杂度O(n), 空间复杂度O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if (!head) return head;
if (head -> val == val) return head -> next;
ListNode* p = head;
while (p -> next ){
if (p -> next -> val == val){
p -> next = p -> next -> next;
return head;
}
p = p -> next;
}
return head;
}
};
“`C++
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
//if the head is null directly return head
if (head == NULL) {
return head;
}
//if the delete node is the head then return the next node of head
if (head->val == val) {
return head->next;
}
ListNode* curr = head->next;
ListNode* prev = head;
while (curr != NULL) {
if (curr->val == val) {
prev->next = curr->next;
curr->next = NULL;
}
prev = curr;
curr = curr->next;
}
return head;
class Solution(object):
def deleteNode(self, head, val):
“””
:type head: ListNode
:type val: int
:rtype: ListNode
“””
#处理特殊情况
if head is None:
return null
if head.val val:
return head.next
#初始化双指针
pre = head
cur = head.next
#正常处理
while cur is not None:
if val cur.val:
pre.next = cur.next
return head
pre,cur = pre.next,cur.next
return head
共以下 54 个回答
打卡成功
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode deleteNode(ListNode* head, int val) {
ListNode* ret = head;
if(head->val val)
{
return head->next;
}
while ((ret->next != nullptr)&&(ret->next->val != val))
{
ret = ret->next;
}
if (ret->next != nullptr)
{
ret->next = ret->next->next;
}
return head;
}
};
遍历一遍链表,找到目标节点,失当前节点指向目标节点下一个节点即可。需注意头节点也也可能是目标节点的情况。
时间复杂度为 O(n),空间复杂度为O(1).
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if (head->val val) {
return head->next;
}
ListNode* last = head;
ListNode* t = head->next;
while (t != NULL) {
if (t->val val){
last->next = t->next;
}
t = t->next;
last = last->next;
}
return head;
}
};
感觉这道题还蛮简单,没想到还记得怎么写hhh
定位节点,修改引用,注意头结点和空节点
class Solution:
def deleteNode(self, head:ListNode, val: int):
if head.val val:
return head.next
pre, cur = head, head.next
while cur and cur.val != val:
pre, cur = cur, cur.next
if cur:
pre.next = cur.next
return head
1.采用前后双指针思路,主要是要考虑边界问题,当head为null或者head.val = val的情况
2.通过while循环,找到值之后终止掉,最后return整个链表
时间复杂度O(n)
空间复杂度O(1)
这里在自己想思路的时候,因为有点混乱,所以一直卡住了,要先判定hed是否为空,不然后边对head的操作都有可能会操作空节点;其次要判定头结点是否是要删除的值来做特殊处理,因为这里给的单链表不是那种带特殊头结点的那种,不能像链表中的节点一样处理,所以要单独处理;最后可以将不管val为null,还是为删除的是链表中的节点都可以统一处理,这个思路是最正确的。
//检测头节点是否为空 返回空
//检测头节点是否为值是否为所设的值 返回节点
//设当前的指针和前指针 遍历整个 替换整个链表 找寻值相同的
java
if(head NULL)
{
return NULL;
}
if(head.val val)
{
return head.next;
}
LIstNode temp = head.next;
LIstNode pre = head;
while(temp !=NULL)//遍历可以从头到尾 也可以判断值是否正确while(temp!=NULL&&temp.valval)
{
if(temp.val val)
{
pre.next=temp.next;//删除节点之后的
return head;
}
temp= temp.next;
pre=pre.next;
}
c++
if(head->val val)
{
return head->next;
}
ListNode *pre = head;
LIstNode *cur = head.next;
while(cur != NULL&&cur ->val != val)//指针的传递有两种1 直接移入下一个 或者换成另一个
{
pre = cur;
cur ->cur->next;
}
if(cur !=NULL)
{
pre->next = cur ->next;//截节点位置
}
return head;
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if(head.val val) return head;
ListNode *pre=head, *cur=head->next;
while(cur !=nullptr &cur->val!=val)
{
pre = cur;
cur = cur->next;
}
if(cur != nulptr) pre->next = cur->next;
return head;
}
时间复杂度:O(N)
空间复杂度:O(1)
采用双指针方式,若curval,直接pre->next=cur->next即可删除指定的节点。
先用C,下回补个java。
struct ListNode* deleteNode(struct ListNode* head, int val){
// 判空
if (head NULL) {
return NULL;
}
// 头判断
if (head->val val) {
head = head->next;
return head;
}
// 双指针遍历
struct ListNode *cur = head;
struct ListNode *pre = NULL;
while (cur->next != NULL) {
pre = cur;
cur = cur->next;
if (cur->val val) {
pre->next = cur->next;
return head;
}
}
// 返回
return head;
}
时间复杂度O(n),空间复杂度O(1).。
时间复杂度O(n)
空间复杂度O(1)
class Solution {
public ListNode deleteNode(ListNode head, int val) {
}
事件复杂度:o(n),空间复杂度o(1)
思路:维护一个先前节点指针和当前节点指针,判断当前节点值是否等于要删除值,等于的话讲先前节点下一节点指向当前节点下一节点,要注意判断首节点是要删除的节点的情况。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode deleteNode(ListNode* head, int val) {
ListNode *cur, *per;
if (head->val val) {
return head->next;
}
per = head;
cur = head->next;
while (cur != nullptr && cur->val != val) {
per = cur;
cur = cur->next;
}
if (cur != nullptr) per->next = cur->next;
return head;
}
};
”’java
时间复杂度O(n)空间复杂度O(1)
思路:处理好空节点和首节点即可
//单链表删除节点
public class Solution {
public ListNode deleteNode(ListNode head, int val)
{
ListNode node = head;
if(head.val val) {
head = head.next;
return head;
}
}
时间复杂度:o(m),空间复杂度o(1)
先判断头结点;
再判断后续节点;
思路:
首先就是先排除空链表和首节点的情况,
其次就是遍历整个链表,找出等于val的值并删除。
时间复杂度,o(n)
看见复杂度,o(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode deleteNode(ListNode* head, int val) {
if(headNULL)return head;
if(head->valval)return head->next;
ListNode*p=head;
while(p->next&&p->next->val!=val)
p=p->next;
p->next=p->next->next;
return head;
}
};
思路:
1.头节点是否为空,为空return null
2.删除的元素为第一个元素,直接删除,返回head.next
3.删除的元素不是第一个元素
4.循环查找后续的节点值是否符合条件
时间复杂度:O(n)
空间复杂度:O(1)
Code
TypeScript
单指针
func deleteNode(head *ListNode, val int) *ListNode {
if head.Val val {
return ead.Next
}
}
java代码实现:
思路:创建一个新节点作为头节点,可以防止头节点是要删除的节点;之后直接遍历即可,找到要删除的节点删除即可
时间复杂度:O(n),空间复杂度O(1)
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head null) {
return head;
}
ListNode pre = new ListNode(0);
ListNode cur = head;
pre.next = cur;
head = pre;
while(cur != null) {
if(cur.val val) {
pre.next = cur.next;
}
pre = cur;
cur = cur.next;
}
}
思路
已知头指针和节点值val,删除节点需要一个指针记录当前节点cur,一个指针记录上一个节点pre,当搜索到当前节点的值与val值相同时就需要先把当前节点指的下一个节点赋给上一个节点指的下一个节点,然后再正常向后移。另外,还需要特殊考虑链表为空和第一个节点就等于val的情况。
时间复杂度:O(n)
空间复杂度:O(1)
Code
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode deleteNode(ListNode* head, int val) {
if(headNULL) return NULL;
if(head->valval) return head->next;
ListNode *pre=head;
ListNode *cur=head->next;
while(cur!=NULL){
if(cur->valval){
pre->next=cur->next;
}
pre=cur;
cur=cur->next;
}
return head;
}
};
ListNode* deleteNode(ListNode* head, int val) {
// 创建一个亚结点
ListNode* dummy = new ListNode(0);
dummy->next = head;
Q:如果想在本地想测试这段代码,应该怎么写前面的调用头
–思路:首先确定双指针法,再特殊处理删除头尾节点情况
–时间复杂度O(n),空间复杂度O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteNode(ListNode head, int val) {
// 先排除val节点是空节点或者头节点
if(headnull){
return null
}
if(head.val=val){
return head.next;
}
ListNode tmp=head.next;
ListNode pre=head;
while(pre!=null){
if(tmp.val=val){
pre.next=tmp.next;
return head;
}
tmp=tmp.next;
pre.next;
}
return head;
}
}
思路就是逐个遍历,找到了就删掉
另个意外情况:为空和头结点就是删除节点
时间复杂度 O(n)
空间复杂度O(1)
ps: c++好像需要释放掉删除的节点空间,但java虚拟机会做这件事
过
“`cpp
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* d = new ListNode(-1);
d->next = head;
ListNode *cur;
cur = d;
while(cur != nullptr && cur->next != nullptr){
if(cur->next->val == val){
cur->next = cur->next->next;
}
cur = cur->next;
}
return d->next;
}
};
链表题目核心则是考虑空节点的next问题,以及前置指针的保留,以及链表的遍历,
(1)可以先考虑异常情况,解决最简单的case
(2)可以单删除操作需要哪些元素
(3)可以考虑正常遍历需要哪些操作
(4)考虑遇到特殊的值的时候应当如何处理
把每个问题拆分的写清楚了,就可以解决这个问题
void delNodeByNum(struct nodeList * head,int num)
{
//判断是否为空链表
if(head NULL)
{
return;
}
struct nodeList *tmp = head;
//判断是否为删除头结点
if(num 1)
{
head = tmp->next;
free(tmp);
return;
}
//找删除节点的前一个节点
for(int i = 1;tmp != NULL && i < num – 1;i++)
{
tmp = tmp->next;
}
//看位置是否超过链表总长
if(tmp NULL || tmp->next NULL)
{
return;
}
//找到准备删除的下一个节点,删除节点并且将节点续上
struct nodeList *nextNode = tmp->next->next;
free(tmp->next);
tmp->next = nextNode;
}
//该删除节点方式是通过检查位数进行删除,遍历链表,时间复杂度o(n),空间复杂度o(1)
void delNodeByval(struct nodeList * head,int value)
{
if(head NULL)
{
return;
}
struct nodeList *tmp = head;
struct nodeList *pre = NULL;
}
//通过寻找相同变量的值进行删除节点
#python解题思路
class Solution(object):
def deleteNode(self, head, val):
“””
:type head: ListNode
:type val: int
:rtype: ListNode
“””
if not head:
return ‘Error’
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if(head NULL){
return head;
}
if(head->val val)
{
return head->next;
}
ListNode *preNode = head;
ListNode *curNode = head->next;
while(curNode != nullptr && curNode->val != val)
{
preNode = curNode;
curNode = curNode->next;
}
if(curNode != nullptr)
{
preNode->next = curNode->next;
}
return head;
}
};
时间复杂度O(n),空间复杂度O(1)
Definition for singly-linked list.
class ListNode:
def init(self, x):
self.val = x
self.next = None
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
dummy = ListNode(0) #初始设置一个伪结点dummy
dummy.next = head
# 若头结点就是要删除的点,则直接返回头结点后面的点
if head.val val:
return head.next
while head and head.next:
#若头结点后面的点是要删除的点,则将要删除点后面一位的值赋给要删除点,这样就将要删除点给删除了
if head.next.val val:
head.next = head.next.next
head = head.next
return dummy.next
时间复杂度:O(n),空间复杂度:O(1)
//时间复杂度o(n),只要是链表查找时间,先定义一个指针,从头结点开始,他的下一个next不为空的前提下p->next->val和目标值匹配;成功就跳出;然后就替换;输出
struct ListNode* deleteNode(struct ListNode* head, int val){
if(head->val val) {
return head->next;
}
struct ListNode *pre=head;
for(int i=0;((pre->next!=NULL)&& (pre->next->val=!val));i++){
pre=pre->next;
}
if((pre->next!=NULL))
pre->next=pre->next->next;
return head;}
//时间复杂度o(n)链表,前驱指针pre,后驱cur-》next
struct ListNode* deleteNode(struct ListNode* head, int val){
if(head->val val) {
return head->next;
}
struct ListNode *pre=head;
struct ListNode *cur=head;
while((cur!=NULL)&& (cur->val!=val)){
pre=cur;
cur=cur->next
}
if(cur!=NULL)
pre->next=cur->next;
return head;
}
思路:首先确定双指针法,再特殊处理删除头尾节点情况
时间复杂度O(n),空间复杂度O(1)
/**
*打卡
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head null)
return null;
if(head.val val){
return head.next;
}
}
时间 on,空间o1
打卡,基础题
“`python
打卡
Definition for singly-linked list.
class ListNode:
def init(self, x):
self.val = x
self.next = None
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
tmp = ListNode(0)
tmp.next = head
node = head
pre = tmp
思路:通过修改指针的指向关系来实现删除效果
解题方法:
如果头节点就是要删除的,直接返回头节点的下一个节点 否则遍历链表,找到节点前一个节点 将前一个节点的next指向下下个节点,实现跳过删除效果 最后返回新的头节点
时间复杂度:O(n)
空间复杂度:O(1)
打卡
时间复杂度:O(n),空间复杂度:O(1)
特殊考虑head,用两个节点来连接删除后的链表
1.边界第一个节点直接判断,是指定节点直接返回其next;
2.然后使用指针p遍历链表,last指针表示上一个节点,遍历到直接将last的next指向p的next;
3.返回head;
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode deleteNode(ListNode* head, int val) {
if (head->val val) {
return head->next;
}
auto *last = head;
for (auto *p = head->next; p != nullptr; p = p->next, last = last->next) {
if (p->val val) {
last->next = p->next;
break;
}
}
return head;
};
1.TC : O(n) SC: O(1)
2.利用prev 儲存刪除節點前一個節點 並用curr去遍歷所有節點
3.頭節點的corner case要優先判斷
“`C++
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
}
“`
注意while判断条件不是p.next != null
public ListNode deleteNode(ListNode head, int val) {
if(head null) return null;
if(head.val val) return head.next;
ListNode p = head;
ListNode pre = new ListNode(-1);
// pre.next = p;
while(p != null){
int cur = p.val;
if(val cur){
pre.next = p.next;
p.next = null;
return head;
}
pre = p;
p = p.next;
}
两个指针向后判断就可以不需要加cur != null,因为cur不可能为null
class Solution {
public ListNode deleteNode(ListNode head, int val) {
ListNode pre = head,cur=head.next;
if(head.val val) return head.next;
while(cur.val !=val){
pre = cur;
cur = cur.next;
}
pre.next = cur.next;
return head;
}
}
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode deleteNode(ListNode* head, int val) {
if(head NULL) return NULL; //当头指针为空,返回空指针;
};
class Solution(object):
def deleteNode(self, head, val):
“””
:type head: ListNode
:type val: int
:rtype: ListNode
“””
#处理特殊情况
if head is None:
return null
if head.val val:
return head.next
#初始化双指针
pre = head
cur = head.next
#正常处理
while cur is not None:
if val cur.val:
pre.next = cur.next
return head
pre,cur = pre.next,cur.next
return head
针对头节点需要进行特殊处理,如果是头节点,直接返回头节点的下一个节点;不是的话,设置前后两个指针,遍历到待删除节点,删除即可
时间复杂度: O(n);空间复杂度: O(1)
头结点单独判断
时间复杂度O(n),空间复杂度O(1)。
双指针
时间O(n)空间O(1)
1、基本题
2、时间复杂度O(n),空间复杂度O(1)