每日算法題 | 劍指offer 鏈表專題 (5)鏈表中倒數第k個節點

重磅乾貨,第一時間送達程序員

每日算法題 | 劍指offer 鏈表專題 (5)鏈表中倒數第k個節點

題目

鏈表中倒數第k個節點面試

題目要求

輸入一個鏈表的頭結點,從尾到頭反過來打印出每一個結點的值正則表達式

解題思路

爲了獲得倒數第k個結點,很天然的想法是先走到鏈表的尾端,再從尾端回溯k步。當時,從鏈表結點的定義能夠看出本題中的鏈表是單向鏈表,單向鏈表的結點只有從前日後的指針而沒有從後往前的指針,所以這種思路行不通,它只適用於雙向鏈表。
思路:看到本題咱們很天然的一個想法是從尾結點往前倒退k步,可是對於單鏈表是行不通的。那咱們換個思路,假設鏈表有n個結點,要求倒數第k個結點,其實也就是從前日後數第n-k+1個結點,這個思路只須要遍歷兩次鏈表便可。 算法

  有沒有隻遍歷一次鏈表的方法呢?本題實際上是很典型的快慢雙指針問題,快指針先走k步,而後快慢指針再同時往前走,當快指針走到盡頭時,慢指針恰好在倒數第k個節點的位置上。這樣只須要遍歷一次鏈表便可。惟一須要注意的問題是當心參數k值大於鏈表長度。數組

每日算法題 | 劍指offer 鏈表專題 (5)鏈表中倒數第k個節點

代碼實現

Python :

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        pre = post = head
        # 快指針先走k步
        for i in range(k):
            # 若是k大於鏈表長度,返回空
            if pre == None:
                return None
            pre = pre.next
        # 快慢指針同時往前走
        while pre != None:
            pre = pre.next
            post = post.next
        return post

C++

/*
struct ListNode {
  int val;
  struct ListNode *next;
  ListNode(int x) :
      val(x), next(NULL) {
  }
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        // 查找倒數第0個節點和輸入空指針
      if(pListHead == NULL || k == 0){
            return NULL;
        }

        // 兩個指針遍歷鏈表
        ListNode *pAhead = pListHead;
        ListNode *pBehind = pListHead;

        // 第一個指針從鏈表的頭結點走K-1步
        for(unsigned int i = 0; i < k - 1; i++){
            if(pAhead->next != NULL){
                pAhead = pAhead->next;
            }
            else{
                return NULL;
            }
        }

        // 第k個節點開始,兩個指針同時遍歷
        while(pAhead->next != NULL){
            pAhead = pAhead->next;
            pBehind = pBehind->next;
        }
        return pBehind;
    }
};

JAVA

/**
 * 輸入一個鏈表,輸出該鏈表中倒數第k哥結點。
 * 爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾結點是倒數第1個結點。
 * 例如一個鏈表有6個結點,從頭結點開始它們的值依次是1,2,3,4,5,6.這個鏈表的倒數第3個結點是值爲4的結點
 */
package swordForOffer;

import utils.ListNode;

public class E15KthNodeFromEnd {
  public ListNode FindKthToTail(ListNode head,int k){
    if(head == null || k <= 0){
      return null;
    }
    ListNode ANode = head;
    ListNode BNode = null;
    for(int i = 0;i<k-1;i++){
      if(ANode.next != null)
        ANode = ANode.next;
      else
        return null;
    }
    BNode = head;
    while(ANode.next != null){
      ANode = ANode.next;
      BNode = BNode.next;
    }
    return BNode;
  }
  public static void main(String[] args){
    ListNode head = new ListNode();
    ListNode second = new ListNode();
    ListNode third = new ListNode();
    ListNode forth = new ListNode();
    head.next = second;
    second.next = third;
    third.next = forth;
    head.data = 1;
    second.data = 2;
    third.data = 3;
    forth.data = 4;
    E15KthNodeFromEnd test = new E15KthNodeFromEnd();
    ListNode result = test.FindKthToTail(head, -1);
    System.out.println(result);
  }
}

後記

注:面試季來了,無論是做爲面試者仍是之後做爲面試官,瞭解算法這門程序員之間的溝通方式都是很是必要的。找過工做的朋友應該都據說過《劍指offer》,雖然書中只有六十多道題目,可是道道都是經典。微信

若是是單純的面試需求,劍指offer的優先級確定是在Leetcode以前,總的說它有三個優勢:數據結構

  • 1.極可能在面試中出現原題
  • 2.約66題,題量少,可是涵蓋的內容較全
  • 3.能培養一個良好的刷題習慣

它的缺點是:機器學習

  • 1.只有66題,刷着容易過擬合
  • 2.動態規劃的題比較少,所以須要在Leetcode上專項訓練。
    算法題主要分紅數據結構和具體算法部分,簡單歸類以下。基本每道題都很精彩,因此這裏就不一一洗寫了,題解能夠看看個人代碼倉庫或者討論區的內容。

數據結構類題目

  • LinkedList
  • 003-從尾到頭打印鏈表
  • 014-鏈表中倒數第k個結點
  • 015-反轉鏈表
  • 016-合併兩個或k個有序鏈表
  • 025-複雜鏈表的複製
  • 036-兩個鏈表的第一個公共結點
  • 055-鏈表中環的入口結點
  • 056-刪除鏈表中重複的結點
  • Tree
  • 004-重建二叉樹
  • 017-樹的子結構
  • 018-二叉樹的鏡像
  • 022-從上往下打印二叉樹
  • 023-二叉搜索樹的後序遍歷序列
  • 024-二叉樹中和爲某一值的路徑
  • 026-二叉搜索樹與雙向鏈表
  • 038-二叉樹的深度
  • 039-平衡二叉樹
  • 057-二叉樹的下一個結點
  • 058-對稱的二叉樹
  • 059-按之字形順序打印二叉樹
  • 060-把二叉樹打印成多行
  • 061-序列化二叉樹
  • 062-二叉搜索樹的第k個結點
  • Stack & Queue
  • 005-用兩個棧實現隊列
  • 020-包含min函數的棧
  • 021-棧的壓入、彈出序列
  • 044-翻轉單詞順序列(棧)
  • 064-滑動窗口的最大值(雙端隊列)
  • Heap
  • 029-最小的K個數
  • Hash Table
  • 034-第一個只出現一次的字符
  • 065-矩陣中的路徑(BFS)
  • 066-機器人的運動範圍(DFS)
  • 具體算法類題目
  • 斐波那契數列
  • 007-斐波拉契數列
  • 008-跳臺階
  • 009-變態跳臺階
  • 010-矩形覆蓋
  • 搜索算法
  • 001-二維數組查找
  • 006-旋轉數組的最小數字(二分查找)
  • 037-數字在排序數組中出現的次數(二分查找)
  • 全排列
  • 027-字符串的排列
  • 動態規劃
  • 030-連續子數組的最大和
  • 052-正則表達式匹配(我用的暴力)
  • 回溯
  • 065-矩陣中的路徑(BFS)
  • 066-機器人的運動範圍(DFS)
  • 排序
  • 035-數組中的逆序對(歸併排序)
  • 029-最小的K個數(堆排序)
  • 029-最小的K個數(快速排序)
  • 位運算
  • 011-二進制中1的個數
  • 012-數值的整數次方
  • 040-數組中只出現一次的數字
  • 其餘算法
  • 002-替換空格
  • 013-調整數組順序使奇數位於偶數前面
  • 028-數組中出現次數超過一半的數字
  • 031-整數中1出現的次數(從1到n整數中1出現的次數)
  • 032-把數組排成最小的數
  • 033-醜數
  • 041-和爲S的連續正數序列(滑動窗口思想)
  • 042-和爲S的兩個數字(雙指針思想)
  • 043-左旋轉字符串(矩陣翻轉)
  • 046-孩子們的遊戲-圓圈中最後剩下的數(約瑟夫環)
  • 051-構建乘積數組

劍指offer刷題交流羣ide

掃碼添加微信,必定要備註研究方向+地點+學校+暱稱(如機器學習+上海+上交+湯姆)函數

每日算法題 | 劍指offer 鏈表專題 (5)鏈表中倒數第k個節點
▲長按加羣

每日算法題 | 劍指offer 鏈表專題 (5)鏈表中倒數第k個節點

相關文章
相關標籤/搜索