/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode l, r;
l = r = head;
for (int i = 0; i < k; i++) {
r = r.next;
// 不够k个节点
if (i < k - 1 && r == null) return null;
}
while (r != null) {
l = l.next;
r = r.next;
}
return l;
}
}
class Solution:
def FindKthToTail(self , pHead: ListNode, k: int) -> ListNode:
# 快指针比慢指针多走k步,那么当快指针遍历完,[慢指针]刚好是到倒数k的位置
fast = pHead
slow = pHead
# 快指针走的时候,慢指针不走
for i in range(0, k):
if not fast:
return None
fast = fast.next # 表示指针在遍历
# 两个指针开始同时走
while fast:
fast = fast.next
slow = slow.next
return slow
def getKthFromEnd(head:ListNode,k:int)->ListNode:
'''
使用双指针,一个先走k步,然后两个同时走k-1步,当先走的那个走到终点时,后走的指针到达倒数第k个节点
:param head: 头节点
:param k: 倒是第k个节点
:return: 头节点
'''
if not head:
return head
# 先走的指针
first = head
# 后走的指针
second = head
# first指针先走k-1步
for _ in range(k-1):
first = first.next
# 双指针同时走
while first.next:
first = first.next
second = second.next
return second
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
fast,slow=head,head
#让快指针比慢指针多走K
for _ in range(k):
if not fast:return fast
fast=fast.next
#当快指针到NULL的时候,慢指针就是倒数第K个节点
while fast:
fast,slow=fast.next,slow.next
return slow
class Solution(object):
def getKthFromEnd(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
fast = slow = head
i = 0
while fast:
if i >= k:
slow = slow.next
fast = fast.next
i += 1
return slow
时间复杂度 O(n)
空间复杂度 O(1)
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode pre = head;
ListNode temp = head;
int i = 0;
while (temp != null) {
if (i >= k){
pre = pre.next;
}
temp = temp .next;
i++;
}
return pre;
}
}
public ListNode getKthFromEnd1 (ListNode head, int k) {
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
// 1. 设置两个指针
ListNode A = dummyHead;
ListNode B = dummyHead;
// 2. 移动其中一个指针k个节点
for (int i = 0; i < k; i++) {
if (A == null) {
return null;
}
A = A.next;
}
// 3. 同时移动两个节点,直到先移动的指针遍历完成
while (A != null) {
A = A.next;
B = B.next;
}
return B;
}
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
# 解体方法:快慢指针
fast ,slow = head, head
#先将快指针移动到第k+1个节点
while fast and k > 0:
fast = fast.next
k -= 1
#同时移动快慢指针到各自的下一节点,指导快指针指向尾节点,此时的慢指针指向倒数第k个节点
while fast:
fast = fast.next
slow = slow.next
return slow
func getKthFromEnd(head *ListNode, k int) *ListNode {
if head == nil {
return head
}
slow, fast := head, head
for i := 0; i < k; i++ {
// 链表的长度没有k
if fast == nil {
return nil
}
fast = fast.Next
}
for fast != nil {
slow = slow.Next
fast = fast.Next
}
return slow
}
class Solution(object):
def getKthFromEnd(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
l = 0
x = head
while(x):
l += 1
x = x.next
for i in range(l-k):
head = head.next
return head
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
if(head.next == null) return head;
int count = 1;
ListNode list = head;
while(list.next!=null){
list = list.next;
count++;
}
ListNode li = head;
for(int i = 1;i<=count-k;i++){
li = li.next;
}
return li;
}
}
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
pre, cur = head, head
for _ in range(k):
cur = cur.next
while cur:
pre = pre.next
cur = cur.next
return pre
public class Solution {
public ListNode getKthFromEnd(ListNode head , int k) {
//1.按照帅地的思路解题:设置快慢指针,两个相差k
if (k < 0)
throw new IllegalArgumentException("get failed,cause k is illegal.");
if (head == null)
return null;
ListNode pre = head;
ListNode cur = head;
for (int i = 0; i < k; i++) {
cur = cur.next;
}
while (cur != null) {
cur = cur.next;
pre = pre.next;
}
return pre;
}
}
class Solution2 {
public ListNode getKthFromEnd(ListNode head , int k) {
//题目的关键在于找到第k个元素,因此可以简单循环遍历一下
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode prev = dummyHead;
//计算出一共有多少元素
int count = 0;
while (prev.next != null) {
count++;
prev = prev.next;
}
ListNode ret = dummyHead;
//倒数第k个,就是正数第count-k+1个
for (int i = 0; i < count - k + 1; i++) {
ret = ret.next;
}
return ret;
}
}
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
if (head == null) return null;
ListNode pre = head;
ListNode cur = head;
for (int i = 0; i < k; ++i) {
cur = cur.next;
}
while (cur != null) {
pre = pre.next;
cur = cur.next;
}
return pre;
}
}
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode pre = head;
ListNode cur = head;
for (int i = 0; i < k - 1; i++) {
cur = cur.next;
}
while(cur.next != null) {
cur = cur.next;
pre = pre.next;
}
return pre;
}
}
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode slow = head;
ListNode fast = head;
for (int i = 1; i < k; i++) {
fast = fast.next;
}
while (fast.next != null){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
//先定义两个指针p,r指向头结点,第一次遍历r获得链表的长度,第二次遍历p到链表的r-k+1位置处。
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
int len = 1; //len记录链表的长度
ListNode p = head;
ListNode r = p;
while(r.next != null){
len++;
r = r.next;
}
//len表示链表的总长度,则需要删除的节点在链表中的位置为len-k+1
for(int i=1; i<=len-k; i++){
p = p.next; //使p指针指向被删除的节点
}
head = p;
return head;
}
}
class Solution(object):
def getKthFromEnd(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
cur = head
tex = head
<pre><code> for i in range(k-1):
cur= cur.next
while cur.next!=None:
tex = tex.next
cur= cur.next
return tex
</code></pre>
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode fast = head;
ListNode slow = head;
for (int i = 0; i < k; i++) {
fast = fast.next;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode left = head;
ListNode right = head;
for(int i = 0; i < k; i++){
right = right.next;
}
while(right != null){
left = left.next;
right = right.next;
}
return left;
}
}
共以下 94 个回答
下面是代码
Definition for singly-linked list.
class ListNode:
def init(self, x):
self.val = x
self.next = None
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
fast,slow=head,head
#让快指针比慢指针多走K
for _ in range(k):
if not fast:return fast
fast=fast.next
#当快指针到NULL的时候,慢指针就是倒数第K个节点
while fast:
fast,slow=fast.next,slow.next
return slow
static class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode prek = head;
ListNode cur = head;
while(cur.next != null){
cur = cur.next;
k–;
if(k <= 0){
prek = prek.next;
}
}
return prek;
}
}
空间O(1)
时间O (n)
快慢指针方法
空间O(1)
时间O (n)
快慢指针方法
空间O(1)
时间O (n)
代码如下:
“`c++“`
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
if(head == NULL)
return NULL;
ListNode *p = head;
ListNode *q = head;
while(k– && p!=NULL)
{
p = p->next;
}
while(p)
{
p = p->next;
q = q->next;
}
return q;
};
时间复杂度:O(n)
空间复杂度:O(1)
新手打卡
/思路
*先得到链表的结点总数,再利用循环遍历到倒数第K个结点/
java
快慢指针,一个移动k另一个再移动
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode fastNode=head;
ListNode slowNode=head;
for(int i = 0;i<k;i++){
fastNode=fastNode.next;
}
while(fastNode!=null){
fastNode=fastNode.next;
slowNode=slowNode.next;
}
return slowNode;
}
复杂度:
时间复杂度为O(n),空间复杂度为O(1)
时间复杂度O(n)
空间复杂度O(1)
1、两个指针,慢的指向头,快的指向第k个结点(如果有)。接下来快慢同步++,直到快的为nullptr停止,此时慢的刚好指向了倒数第k个节点。
2、时间复杂度O(n),空间复杂度O(1)
打卡C++
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode* cur = head;
};
时间复杂度 n
空间复杂度 1
//c++实现
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode* dummy=new ListNode(0,head);
ListNode* l=dummy;
ListNode* r=dummy;
while(k–) r=r->next;
while(r->next){
r=r->next;
l=l->next;
}
return l->next;
};
时间复杂度:O(n),其中 n=length为链表的长度。需要两次遍历。
空间复杂度:O(1)。
时间复杂度o(N)
空间复杂度o(1)
解法一:使用快慢指针
解法二:求链表长度n,走(n-k)步
时间复杂度均为:O(n)
空间复杂度均为:O(1)
双指针
1. 时间复杂度:O(n)
2. 空间复杂度:O(1)
3. 代码
时间复杂度O(n)
空间复杂度O(1)
“`java
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
//首先判断特殊情况,只有一个头节点
if (head == null) {
return head;
}
时间复杂度:O(n)
空间复杂度:O(1)
方法二:使用数学的方法,通过遍历链表得到链表长度n,从前往后遍历,第n-k个节点即为倒数第k个节点,具有相同时间和空间复杂度
1,通过地哥给的提示,一个快指针,一个慢指针。快指针先走k,之后同步走。
2,时间复杂度O(n),空间复杂度不清楚。
结合题目提示,可以采用两个指针,先让快指针与慢指针的间隔为k-1(倒数第几个是从1开始查),然后快慢指针同时走,当快指针访问到null 时,慢指针即是倒数第k个指针,巧妙。
时间复杂度 O(n)
空间复杂度 O(1)
时间复杂度O(N)
空间复杂度O(1)
解法:快慢指针
思路:fast 比 slow 多走 k 步,然后 slow 和 fast 一起走,当 fast = null 时,slow 正好是倒数第 k 个节点
时间复杂度:O(n)
空间复杂度:O(1)
刚接触到快慢指针,一开始不会使用,使用的是先求出链表长度,再用链表长度减去k,得到倒数第k个结点在正数第几个位置,然后通过for循环达到
快慢指针的解题思路
1.关系:链表空指针(NULL)和倒数第k个结点差距为k个距离
2.可以设置fast指针和slow指针
3.先让fast指针先走k步,再让fast和slow同步进行
4.等fast达到NULL时,slow就是倒数第k个结点
时间复杂度O(n)
空间复杂度O(1)
思路:快慢指针,考虑越界等问题
时间复杂度: O(n)
空间复杂度: O(1)
思路: 快慢指针
a.初始化快慢指针
b.fast向后移动k个位置,然后fast和slow再一起向后移动;
c.当fast走到最后的时候,slow的位置就是倒数第k个位置
● 时间复杂度: O(n)
● 空间复杂度: O(1)
时间复杂度:O(n)
空间复杂度:O(1)
顺序查找,算出长度。然后找到k的位置就是长度size-k的值
空间复杂度O(1)
时间复杂度O(n);
//时间复杂度 O(n)
//空间复杂度O(1)
指针指向链表结尾:p nullptr;
三种思路:
思路一:把链表翻转,从链表头节点走k步,并将前面k个节点再翻转。时间复杂度O(N),空间复杂度O(1)。
思路二:先遍历链表,得到链表长度len,从头节点走len – k步。时间复杂度O(N),空间复杂度O(1)。
思路三: 快慢指针,快指针先走k步,随后慢指针和快指针一起走,当快指针遍历完链表后,慢指针正好走到倒数第k个节点。时间复杂度O(N),空间复杂度O(1)。
思路:
本题适合使用快慢指针,让快指针fast先走k步,然后快慢指针一起循环链表,当快指针fast走到链表尾部的时候(fast指针走到null时),慢指针所在位置就为链表中倒数第k个节点了。
时间复杂度 O(n)
空间复杂度 O(1)
额
快慢指针,一次遍历
先遍历求出该链表有多少个节点,
然后-去k,
得到他从哪个节点开始
再定义一个新头结点(这里好像感觉不用,直接用head就行),i=1开始,遍历到count-k,返回新的头结点
时间复杂度:O(n)
空间复杂度:O(1)
用双指针来做
1、先定义两个指针 pre cur 同时指向头节点
2、用一个for循环让cur指针先走k步
3、while循环,当cur NULL时,pre指针所指向的就是倒数第k个节点,将pre返回就可以
时间复杂度O(n) 空间复杂度O(1)
用双指针来做,前后指针相差k,当后指针指向末尾,前指针正好指向倒数第k个节点,返回即可
双指针/快慢指针
时间复杂度:O(N)
空间复杂度:O(1)
代码
时间复杂度:O(n)
空间复杂度:O(1)
时间复杂度O(n)空间复杂度O(1)
###
时间复杂度 O(n)
时间O(n), 空间O(1)
快慢指针,快指针先走k步,快慢指针再一起走,当快指针走到头的时候,此时慢指针指向的节点就是倒数第k个
时间复杂度O(n) — 只需遍历一次
空间复杂度O(1)
双指针
注意看题
用虚拟头结点,遍历到第 链表长度-k 个节点返回
先后两个节点,快速节点先走k步,然后两个节点一起走,知道快速节点到头,慢速节点就是倒数第k个节点
下面是代码
先计算出链表长度,再n-k找到相应节点
差点看成删除链表中的倒数第K个节点了
第一天第二题
//先定义两个指针p,r指向头结点,第一次遍历r获得链表的长度,第二次遍历p到链表的r-k+1位置处。
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
int len = 1; //len记录链表的长度
ListNode p = head;
ListNode r = p;
while(r.next != null){
len++;
r = r.next;
}
//len表示链表的总长度,则需要删除的节点在链表中的位置为len-k+1
for(int i=1; i<=len-k; i++){
p = p.next; //使p指针指向被删除的节点
}
head = p;
return head;
}
}
这里使用的是快慢指针的方法,快与慢的就是倒数数字
细节:虚拟节点的快慢节拍以及最后返回指针的指向
简单实现之前文中的做法
“`java
“`java
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
//如果头节点为0 k小于等于0 返回空
if( head == null || k <= 0){ return null; } //定义前后指针 ListNode fast = head; ListNode slow =head; //先让前指针走k步 while(fast !=null && k >0 ){
fast = fast.next;
k–;
}
让一个指针temp先走k步,再让temp与head一起移动,当temp到链表尾的时候,head到倒数第K个节点
让cur先走k-1,然后tex和cur一起走,退出条件 cur.next=None
简单
双指针,p1走K步,p1,p2 再同步走
随便写
因为知道要用快慢指针,所以倒没遇到什么坑,就注意 i 应该从1开始
双指针
快慢指针的运用
注意本题从1开始计数