力扣-19-删除链表倒数第N个结点/《剑指Offer》-22-链表中倒数第K个节点

可以看出,《剑指Offer》-22是力扣-19的子问题

找到链表中倒数第K个节点

《剑指Offer》-22,一次遍历单向链表得到倒数第K个结点的方法

从1开始倒数,那么倒数第K个节点即是正数第N-K+1个节点

这里还是使用同向双指针的办法

pointer1/pointer2都初始化为指向0,pointer1先开始走而pointer2不动,当pointer1走完第K-1步后,pointer2开始同步pointer1往后走,这样始终保持了两个指针间距为K-1
则最终,当pointer1指向第N个节点时,pointer2指向的便是第N-K+1个节点,即倒数第K个节点

代码实现

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* temp = new ListNode(0,head);
        ListNode* pointer1=head;
        ListNode* pointer2=temp;
        // 这里不需要做检查,n一定是合法的
        for(int i=0;i<n;++i){
            pointer1 = pointer1->next;
        }
        // 移动
        while(pointer1){
            pointer1=pointer1->next;
            pointer2=pointer2->next; 
        }

        pointer2->next=pointer2->next->next;
        ListNode* ans = temp->next;
        delete temp;
        return ans;
    }
};

也可以原始一点,直接跑两次循环,第一次得到n,第二次再跑n-k+1就是结果

	ListNode* getKthFromEnd(ListNode* head, int k) {
		// 倒数第k个,那么就是正数第…但是又不知道这个链表的长度不是
		// 知道了n其实就很容易了,正数:n-k+1个位置
		int count = 0;
		ListNode* ptr = head;
		while (ptr) {
			count++;
			ptr = ptr->next;
		}
		ptr = head;
		for (int i = 0; i < count - k; i++) {
			ptr = ptr->next;
		}
		return ptr;
	}

官方题解

初级算法里面所谓的“Dummy node”节点技巧就是添加一个指向头节点的节点,目的是为了解决头节点被操作的情况(例如被删了)

《剑指Offer》官解

书中给出的解法关注重点其实是在于代码的鲁棒性,也就是说考虑意外情况:

  1. 头指针为空
  2. k 的长度会不会大于链表长度
  3. k 有没有可能为 0

但事实上大多数时候我们关注的都是解题的思路和技巧,对于非法情况和输入,一般不影响到代码运行都默认没问题

	ListNode* getKthFromEnd(ListNode* head, int k) {
		if (!head || !k) return nullptr;
		ListNode* pre = head;

		for (int i = 0; i < k - 1; i++) {
			if (pre->next) pre = pre->next;
			else return nullptr;
		}

		ListNode* res = head;
		while (pre) {
			pre = pre->next;
			res = res->next;
		}
		return res;
	}
posted @ 2022-06-06 23:49  YaosGHC  阅读(30)  评论(0)    收藏  举报