class Solution(object):
def trainingPlan(self, head, cnt):
“””
:type head: Optional[ListNode]
:type cnt: int
:rtype: Optional[ListNode]
“””
#删除倒数第K个节点,双指针,一指针先走K-1步
fast=slow=head
if headNone or cnt<=0:
return None
while cnt>0 and fast !=None:
fast=fast.next
cnt-=1
while fast!=None:
fast=fast.next
slow=slow.next
return slow
时间复杂度:O(n),空间复杂度:O(1)
快慢指针,快指针先走cnt
class Solution:
def trainingPlan(self, head: Optional[ListNode], cnt: int) -> Optional[ListNode]:
if head is None:
return None
fast = head
slow = head
for i in range(cnt):
if fast is None:
return None
fast = fast.next
while fast != None:
fast = fast.next
slow = slow.next
return slow
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def trainingPlan(self, head, cnt):
"""
:type head: Optional[ListNode]
:type cnt: int
:rtype: Optional[ListNode]
"""
fast = head
slow = head
for _ in range(cnt):
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
return slow
//使用双指针
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
if (head null || head.next null) {
return head;
}
ListNode first = head;
for (int i = 1; i < cnt; i++) {
first = first.next;
}
ListNode second = head;
while (first.next != null) {
first = first.next;
second = second.next;
}
return second;
}
}
ListNode* pre = head;
ListNode* cur = head;
for(int i = 0; i < cnt; i++){
cur = cur->next;
}
while(cur != nullptr){
pre = pre->next;
cur = cur->next;
}
return pre;
}
#题解
var trainingPlan = function (head, cnt) {
let n = 0;
let cur = head;
while (cur) {
cur = cur.next;
n++;
}
cur = head;
for (let i = 0; i < n – cnt; i++) {
cur = cur.next;
}
return cur;
};
class Solution(object):
def trainingPlan(self, head, cnt):
“””
:type head: Optional[ListNode]
:type cnt: int
:rtype: Optional[ListNode]
“””
slow, fast = head, head
for i in range(cnt):
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
return slow
代码:”’java
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy=new ListNode(0,head);
int length =getLength(head);
ListNode cur = dummy;
for(int i=1;i<length-n+1;++i){
cur=cur.next;
}
cur.next=cur.next.next;
ListNode ans = dummy.next;
return ans;
}
public int getLength(ListNode head){
int length=0;
while(head!=null){
++length;
head=head.next;
}
return length;
}
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def trainingPlan(self, head: Optional[ListNode], cnt: int) -> Optional[ListNode]:
fast = head
slow = head
while cnt:
fast = fast.next
cnt -= 1
while fast:
fast = fast.next
slow = slow.next
return slow
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
A = headA
B = headB
while A!=B:
A = A.next if A else headB
B = B.next if B else headA
return A
···java
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode first = head;
ListNode second = head;
int i = 0;
while(i<cnt){
first = first.next;
i++;
}
while(first!=null){
first = first.next;
second = second.next;
}
return second;
}
}
时间复杂度:只遍历了一次链表,O(n),空间复杂度为O(1),额外设置了first和second两个指针。
思路:先让first走cnt步,随后first和second一起走,当first为null的时候,second刚好为第cnt个节点。
共以下 83 个回答
思路
java
首先特殊情况,头节点是否为空
其次指定快慢指针都指向head
然后对快指针进行前进k个位置,并判断是否到达末尾
慢指针和快指针一起前进,抵达末尾会返回慢指针的位置,这就是倒数第k个节点
class Solution(object):
def trainingPlan(self, head, cnt):
“””
:type head: Optional[ListNode]
:type cnt: int
:rtype: Optional[ListNode]
“””
#删除倒数第K个节点,双指针,一指针先走K-1步
fast=slow=head
if headNone or cnt<=0:
return None
while cnt>0 and fast !=None:
fast=fast.next
cnt-=1
while fast!=None:
fast=fast.next
slow=slow.next
return slow
时间复杂度:O(n),空间复杂度:O(1)
“`c++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode *slow = dummyHead;
ListNode *fast = dummyHead;
while (fast->next != nullptr && n–) {
fast = fast->next;
}
fast = fast->next;
//fast和slow同时移动,直到fast指向末尾
while(fast != nullptr) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
};
“`
快慢指针,快指针先走cnt
class Solution:
def trainingPlan(self, head: Optional[ListNode], cnt: int) -> Optional[ListNode]:
if head is None:
return None
fast = head
slow = head
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainingPlan(ListNode* head, int cnt) {
ListNode* a = head;
ListNode* b = head;
while(cnt–)
{a = a->next;}
while(a != NULL)
{
a = a->next;
b = b->next;
}
return b;
};
//自己写的,最后的while判断出现了空指针异常,对于是否是a指向空还是a->next指向空,得有判断,可以画个图
第二次打卡
时间复杂度:O(n) 空间复杂度:O(1)
class Solution:
def trainingPlan(self, head: ListNode, cnt: int) -> ListNode:
former, latter = head, head
for _ in range(cnt):
former = former.next
while former:
former, latter = former.next, latter.next
return latter
//使用双指针
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
if (head null || head.next null) {
return head;
}
ListNode first = head;
for (int i = 1; i < cnt; i++) {
first = first.next;
}
ListNode second = head;
while (first.next != null) {
first = first.next;
second = second.next;
}
return second;
}
}
时间复杂度O(N),空间复杂度O(1)
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
ListNode* pfast=head;
ListNode* pslow=head;
while(cnt–>1){
pfast=pfast->next;
}
while(pfast->next!=nullptr){
pfast=pfast->next;
pslow=pslow->next;
}
return pslow;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainingPlan(ListNode* head, int cnt) {
};
不需要虚拟头节点,快指针本来就要领先
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
if(head null){
return null;
}
int n=1;
ListNode slow = head;
ListNode fast = head;
while(n<cnt){
fast = fast.next;
n++;
}
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
时间复杂复O(n)
时间复杂度是O(n);
空间复杂度是O(1);
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode pre=head,p=head;
while(p!=null&&cnt– >0) p=p.next;
if(pnull) return p;
while(p!=null){
p=p.next;
pre=pre.next;
}
return pre;
}
思路:双指针
时间O(n) 空间O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode next;
* };
*/
struct ListNode trainingPlan(struct ListNode* head, int cnt) {
struct ListNode* latter = head;
struct ListNode* former = head;
for(int i = 0;i<cnt;i++){
former = former->next;
}
while(former!=NULL){
former = former->next;
latter = latter->next;
}
return latter;
}C语言回答,采用了两个指针进行求解
#题解
var trainingPlan = function (head, cnt) {
let n = 0;
let cur = head;
while (cur) {
cur = cur.next;
n++;
}
cur = head;
for (let i = 0; i < n – cnt; i++) {
cur = cur.next;
}
return cur;
};
“` java
思路:快慢双指针的运用,定义两个指针p1和p2,初始时都指向头结点head。然后让p1向前移动k-1次,这样p1就会指向从头开始算起的第(n-k+1)个节点(假设n为链表长度)。接下来同时将p1和p2向前移动,直到p1到达尾部时。此时p2所指向的节点就是倒数第k个节点了。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int k) {
if (head null || k<= 0) return null; // 处理特殊情况
}
时间复杂度:O(n),因为要求完全遍历链表
空间复杂度:O(1),定义了两个指针,使用了常数大小的空间。
/输入一个链表,输出该链表中倒数第k个节点/
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
if(headnullptr){
return nullptr;
}
};
打卡
class Solution {
//时间复杂度O(n),空间复杂度O(1)
public ListNode trainingPlan(ListNode head, int cnt) {
//先处理特殊情况
if(head null) {
return head;
}
//双指针:先走cnt步,再一起走
ListNode temp = head;
while(cnt >= 1) {
temp = temp.next;
cnt–;
}
while(temp != null) {
head = head.next;
temp = temp.next;
}
return head;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
if(head null){
return null;
}
ListNode pre = head,cur = head;
while(cnt != 0){
cur = cur.next;
cnt–;
}
while(cur != null){
cur = cur.next;
pre = pre.next;
}
return pre;
}
}
//快慢双指针的运用。
时间 O(n) 空间 O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
// ListNode dummy = new ListNode(-1);
// dummy.next = head;
}
时间复杂度O(n),空间复杂度O(1)。
时间复杂度o(n),空间复杂度o(1)
注意头为空和列表长度不够k的特殊情况
快慢指针遍历列表,快指针先走k步,在同时走,当快指针为空时,慢指针所处位置即为倒数第k个位置
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainingPlan(ListNode* head, int cnt) {
if(headnullptr)
{
return nullptr;
}
ListNode *fast = head;
ListNode *slow = head;
for(int i =0 ;i < cnt; i++)
{
if(fastnullptr)
{
return nullptr;
}
fast = fast->next;
};
使用双指针,设置temp指针先走cnt – 1次,此时aim指针和temp指针同时走,当temp遍历完链表后,aim指向所求节点
时间复杂度 O(n), 空间复杂度O(1)
双指针,遍历出cnt长度,再同时向表尾遍历。有一个指针走到表尾时,另一个指针就是倒数cnt位置。
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
ListNode *pre=head, *cur = head;
};
空间复杂度:O(1)
时间复杂度:O(n)
class Solution(object):
def trainingPlan(self, head, cnt):
“””
:type head: Optional[ListNode]
:type cnt: int
:rtype: Optional[ListNode]
“””
slow, fast = head, head
for i in range(cnt):
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
return slow
空间复杂度:O(1)
时间复杂度:O(n)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode f = head;
ListNode s = head;
while (cnt!=0)
{
f = f.next;
cnt–;
}
while (f!=null)
{
}提交
java
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode former = head, latter = head;
for(int i = 0; i < cnt; i++){
former = former.next;
}
while(former != null){
former = former.next;
latter = latter.next;
}
return latter;
}
}
提交
python实现
整体思想双指针方法
p1,p2
1.p1先循环cnt次
2.p1再次循环,直到链表尾部,此时循环次数为len(链表)-cnt
p1循环的同时p2也在循环,当循环结束的时候,p2刚好是倒数第cnt个
3.return p2即可
需要考虑的特殊情况
如果cnt大于链表的长度那么直接返回
时间复杂度:o(n)
空间负责度:o(1)
代码:”’java
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy=new ListNode(0,head);
int length =getLength(head);
ListNode cur = dummy;
for(int i=1;i<length-n+1;++i){
cur=cur.next;
}
时间复杂度O(N)
空间复杂度O(1)
”’java
//代码
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode node1=null;
ListNode node2=null;
node1=head;
node2=head;
if(head.nextnull){
return head;
}
for(int i=1;i<cnt;i++){
node2=node2.next;
}
while(node2.next!=null){
node1=node1.next;
node2=node2.next;
}
return node1;
}
}
思路:快慢指针,复杂度:O(n)
代码:
“`java
时间复杂度 O(n)
空间复杂度 O(1)
解题思路:快指针先走k步,快慢指针同时走\n\n具体过程:开始快慢指针都指向头结点,先让快指针走k步,然后快慢指针同时走,当快指针走到空的时候,慢指针的位置即为链表倒数第k个结点的位置。\n\n要注意的是,k的长度可能大于链表结点的长度,fast先走k步会走到空,因此还要要判断fast是否走到空,如果走到空,则返回空。\n\n\n\n
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainingPlan(ListNode* head, int cnt) {
ListNode* slow=head;
ListNode* fast=head;
while(cnt–)
{
if(fastNULL)
{
return NULL;
}
fast=fast->next;
}
while(fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
};
时间复杂度 O(n)
空间复杂度 O(1)
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode virHead=new ListNode(-1);
virHead.next=head;
ListNode fast,slow;
fast=virHead;
slow=virHead;
for(int i=0;i<=n;i++)
fast=fast.next;
while(fast!=null&&slow!=null)
{
fast=fast.next;
slow=slow.next;
}
ListNode temp=slow.next;
slow.next=temp.next;
return virHead.next;
}
}
利用虚拟节点辅助删除节点操作。利用快慢指针锁定位置,其中快的比慢的多走k+1步,锁定被删除节点的前一个位置,就可以删除目标节点。
时间复杂度O(n)
空间复杂度O(1)
双指针问题
fast指针先走k步,当fast走到第k步,slow指针开始出发。
两个指针保持相同的步长,当fast为便利完成时,
slow指针指向的就是目标节点。
时间复杂度O(n):最差情况返回倒数第1的节点。
空间复杂度O(1):两个指针占用常量空间。
让一个指针先走k步,然后两个指针一起向后遍历,当先走的指针指到尾节点时,后出发的指针指向倒数第k个节点,将其删除即可
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode temp = new ListNode(0 , head);
ListNode pre = head;
ListNode second = temp;
for(int i = 0; i < n; i++){
pre = pre.next;
}
while (pre != null){
pre = pre.next;
second = second.next;
}
second.next = second.next.next;
ListNode ans = temp.next;
return ans;
}
}
双指针
fast指针先走k步,
当fast走到第k步,slow指针同时出发。
两个指针保持相同的步长,当fast为None时,
slow指针指向的就是目标节点。
时间复杂度O(n):最差情况返回倒数第1的节点。
空间复杂度O(1):两个指针占用常量空间。
“`C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
ListNode *fast=head;
ListNode *slow=head;
};
\时间复杂度O(n)
\空间复杂度O(1)
“`
让快指针先走cnt步,随后快慢指针一起走,则快指针到底时慢指针就是倒数第cnt个
时间复杂度$O(n)$,空间复杂度$O(1)$
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dumpyHead = new ListNode(-1,head);
ListNode slow = dumpyHead;
ListNode fast = dumpyHead;
for(int i = 0 ; i < n; i++){
fast = fast.next;
}
while(fast.next != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dumpyHead.next;
}
}
时间复杂度O(n)
空间复杂度O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
//快慢指针
ListNode slow = head;
ListNode fast = head;
//fast走cnt,与slow间隔为cnt
for(int i = 0;i<cnt;i++){
fast = fast.next;
}
//共同往后走,间隔cnt个,fast走到null即可
while(fast!=null){
slow = slow.next;
fast = fast.next;
}
时间复杂度O(n)
空间复杂度O(1)
“`python
class Solution:
def trainingPlan(self, head: Optional[ListNode], cnt: int) -> Optional[ListNode]:
pre, cur = head, head
双指针,倒数第K个,先让前指针走K步,前指针为空,返回cur值
时O(N)
空O(1)
时间复杂度O(n)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode next;
* };
*/
struct ListNode trainingPlan(struct ListNode* head, int cnt) {
}
时间复杂度:O(N);空间复杂度O(1)
这题大概的思路是:快指针先走k步,然后快慢指针一起走,直到快指针指向空的时候,快慢指针刚好是倒数第k个
代码:
1.先判断空指针异常
2.快指针先走k步
3.快慢指针此时同时开始往后走,当快指针为空时,慢指针刚好是倒数第k个
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
if(head null){
return null;
}
}
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
ListNode*dummyhead=new ListNode(0);
dummyhead->next=head;
};
时间复杂度:O(N)
空间复杂度:O(1)
使用快慢双指针,fast指针先走cnt步,然后slow指针和fast指针一起走直到fast为空,此时的slow就是倒数第cnt个节点。
时间复杂度O(n);
空间复杂度O(1).
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
if(head null){
return null;
}
ListNode fast = head;
ListNode slow = head;
for(int i = 0; i < cnt;i++){
if(fast null){
return null;
}
fast = fast.next;
}
首先要判断头结点是否为空,创建一个快结点,使其在慢结点后k个位置,此时要注意,万一该链表没有k个结点,后面快和慢同时往后移,当快为空,慢刚好指向倒数第k个结点。
时间复杂度O(n)
空间复杂度O(1)
“`java
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode slow = head, quick = head;
while (cnt– != 0) {
quick = quick.next;
}
while (quick != null) {
quick = quick.next;
slow = slow.next;
}
// slow 和 quick 相差 cnt, quick到了尾节点之后 -> slow和尾节点相差 cnt – 1
return slow;
}
}
“`java
时间复杂度O(n)
空间复杂度O(1)
Definition for singly-linked list.
class ListNode:
def init(self, x):
self.val = x
self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
A = headA
B = headB
while A!=B:
A = A.next if A else headB
B = B.next if B else headA
return A
时间 O(n+m)
空间O(1)常数时间
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainingPlan(ListNode* head, int cnt) {
ListNode* newHead = new ListNode();
newHead->next = head;
ListNode* fast = new ListNode();
ListNode* slow = new ListNode();
fast = newHead;
slow = newHead;
for(int i=0; i<cnt; i++){
fast=fast->next;
}
while(fast->next != NULL){
slow=slow->next;
fast=fast->next;
}
return slow->next;
};
时间复杂度O(n),空间复杂度O(1)
实现思路见注释
时间复杂度O(n),空间复杂度O(1)
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
if(head null){
return null;
}
ListNode qk = head;
ListNode sl = head;
while(cnt>0){
qk = qk.next;
cnt-=1;
}
while(qk != null){
qk = qk.next;
sl = sl.next;
}
return sl;
}
}
时间复杂O(n) 空间复杂O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
/**
* 时间复杂度O(n),空间复杂度O(1)
*/
public ListNode trainingPlan(ListNode head, int cnt) {
if (head null) {
return null;
}
// 创建虚拟头节点
ListNode dumyNode = new ListNode(-1, head);
// 快慢指针
ListNode fastNode = dumyNode;
ListNode slowNode = dumyNode;
// 让快指针先移动n+1
for (int i = 0; i <= cnt; i++) {
fastNode = fastNode.next;
}
// 快慢指针同时移动,直到快指针到尾部
while (fastNode != null) {
fastNode = fastNode.next;
slowNode = slowNode.next;
}
// 直接返回慢指针的下一个节点
return slowNode.next;
}
}
链表中倒数第cnt个节点,java
“`C++
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
ListNode *former = head, *latter = head;
for(int i = 0; i < cnt; i++) { former = former->next;
}
while(former != nullptr)
{
former = former->next;
latter = latter->next;
}
return latter;
}
};
“`
方法:双指针
时间复杂度:o(n)
空间复杂度:o(1)
时间复杂度:O(n)
空间复杂度:O(1)
思路:双指针(fast,slow),让fast先前进cnt步,然后fast和slow一起走,当fast\=\=nullptr时,此时的slow即为倒数第cnt个节点。
“`C++
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
if (head == nullptr) return nullptr;
ListNode *fast = head;
ListNode *slow = head;
while (cnt > 0 && fast != nullptr) {
cnt–;
fast = fast->next;
}
while (fast != nullptr) {
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
“`
如有问题,欢迎指正,谢谢!
时间复杂度o(2n)
空间复杂度o(1)
###c++
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
// 特判
if(head null) return null;
}
class Solution {
public:
ListNode* trainingPlan(ListNode* head, int cnt) {
ListNodep=head,q=head;
for (int i=cnt;i>0;i–) p=p->next;
while(p!=nullptr)
{
p=p->next;
q=q->next;
}
return q;
}
};
打卡
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainingPlan(ListNode head, int cnt) {
// 倒数第k个节点是整数第n-k个节点,使用快慢指针的方法。
if(head nullptr) return nullptr;
ListNode* fast = head;
ListNode* slow = head;
while(cnt–){
fast = fast->next;
}
while(fast != nullptr){
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
时间复杂度O(n),空间复杂度O(1)
···java
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode first = head;
ListNode second = head;
int i = 0;
while(i<cnt){
first = first.next;
i++;
}
while(first!=null){
first = first.next;
second = second.next;
}
return second;
}
}
时间复杂度:只遍历了一次链表,O(n),空间复杂度为O(1),额外设置了first和second两个指针。
思路:先让first走cnt步,随后first和second一起走,当first为null的时候,second刚好为第cnt个节点。
时间复杂度 O(n),空间复杂度 O(1)
//双指针法,p与q之间的距离为k时,但p走到NULL时,q就指向倒数第k个结点
struct ListNode* trainingPlan(struct ListNode* head, int cnt) {
typedef struct ListNode ListNode;
ListNode *p =head, *q=head;
int i=0;
while(i<cnt){
p = p->next;
i++;
}
while(p!=NULL){
p = p->next;
q = q->next;
}
return q;
}
打卡
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainingPlan(ListNode* head, int cnt) {
if(head nullptr) return nullptr;
};
首先判空,让post指针先走cnt个,然后pre和post指针一起走,当post指针为空时,pre指针位置正好
思路
两次遍历,第一遍统计长度len,第二遍检索倒数第cnt个(即正数len+i- 1个,1为起点)训练项目的编号
思考费力的点
遍历的次数+起点+终止条件的确定
时间复杂度
O(n)
空间复杂度
O(1)
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode fastPtr = head;
for(int i = 0; i < cnt; i++){
fastPtr = fastPtr.next;
}
while(fastPtr != null){
fastPtr = fastPtr.next;
head = head.next;
}
return head;
}
双指针
时间复杂度On
空间复杂度O1
快慢指针
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode trainingPlan(ListNode head, int cnt) {
ListNode newHead = new ListNode(0);
newHead.next = head;
ListNode last = newHead;
ListNode fast = newHead;
while(cnt– > 0){
fast = fast.next;
}
while(fast != null){
fast = fast.next;
last = last.next;
}
return last;
}
}
复杂度O(n)
思路:双指针。先计算好快慢指针之间的距离为题目所要求的的数,然后同时向后移动, 当快指针到链表结尾的时候,慢指针所指向的节点就是所求的节点。
时间复杂度:O(n)
空间复杂度:O(1)
快慢指针,快指针要比慢指针快cnt
时间复杂度O(n),空间复杂度O(1)
快慢指针
day1 第二道题