面试题15求链表中倒数第K个结点

https://blog.csdn.net/u010425776/article/details/50879939

 

算法的分析过程均在代码注释中:

 

 
  1. /**

  2. * 题目:输入一个单链表,输出该链表从后往前的第k个数。

  3. * PS:从后往前数时从1开始计数。

  4. * @author 柴毛毛大闲人

  5. */

  6. public class TailK {

  7.  
  8. /**

  9. * 分析:要寻找倒数第k个数,很自然想到的方法是:从末尾向前找第k个数。

  10. * 然而这种方法面临两个问题:1.我们无法直到单链表的末尾在哪儿,2.我们无法从后向前遍历单链表。

  11. * 为了解决上述两个问题,我们首先想到的方法是:遍历两次单链表,第一次求得单链表的长度n,第二次遍历到第n-k个元素停止即可。

  12. * 代码如下:

  13. */

  14.  
  15. //使用全局变量result表示函数运行结果

  16. static boolean result = true;

  17. /**

  18. * @param first 单链表的首结点

  19. * @param k 要找的倒数第几个元素

  20. * @return 返回倒数第K个值

  21. */

  22. public static int getTailK(Node<Integer> first,int k){

  23. //若链表为空

  24. if(first==null){

  25. System.out.println("链表为空!");

  26. result = false;

  27. return 0;

  28. }

  29.  
  30. //若k<=0

  31. if(k<1){

  32. System.out.println("k不能小于1!");

  33. result = false;

  34. return 0;

  35. }

  36.  
  37. //计算链表长度

  38. int length = 1;

  39. Node<Integer> p = first;

  40. while(p.next!=null){

  41. length++;

  42. p = p.next;

  43. }

  44.  
  45. //若k比链表还长

  46. if(length<k){

  47. System.out.println("k="+k+"超过了链表长度!");

  48. result = false;

  49. return 0;

  50. }

  51.  
  52. //遍历链表,遍历到第n-k个元素结束

  53. Node<Integer> q = first;

  54. for(int i=0;i<length-k;i++)

  55. q = q.next;

  56.  
  57. return q.data;

  58. }

  59.  
  60. /**

  61. * 上述方法能解决问题,但需要遍历链表两次,能否有更高效的办法?

  62. * 可以使用两个指针i和j,指针i从头开始先走k步,然后j指向第一个结点,接下来保持i和j之间的距离,当j走到尾时,i指向的结点就是倒数第k个结点。

  63. * 代码如下:

  64. */

  65. public static int getTailK_modify(Node<Integer> first,int k){

  66. //若链表为空

  67. if(first==null){

  68. System.out.println("链表为空!");

  69. result = false;

  70. return 0;

  71. }

  72.  
  73. //若k<=0

  74. if(k<1){

  75. System.out.println("k不能小于1!");

  76. result = false;

  77. return 0;

  78. }

  79.  
  80. //定义两个指针p和q,p指向头结点,q指向第k个结点

  81. Node<Integer> p = first;

  82. Node<Integer> q = first;

  83. //将q指向第k个结点

  84. for(int i=0;i<k-1;i++){

  85. //若q还没指向第k个结点,但q已经是最后一个结点,则说明k超过了链表长度

  86. if(q.next==null){

  87. System.out.println("k="+k+"超过了链表长度!");

  88. result = false;

  89. return 0;

  90. }

  91. q = q.next;

  92. }

  93.  
  94. //p和q分别向后移动,直到q走到链表末尾为止

  95. while(q.next!=null){

  96. p = p.next;

  97. q = q.next;

  98. }

  99.  
  100. return p.data;

  101. }

  102.  
  103.  
  104.  
  105. /**

  106. * 测试

  107. */

  108. public static void main(String[] args){

  109. Node<Integer> node1 = new Node<Integer>();

  110. Node<Integer> node2 = new Node<Integer>();

  111. Node<Integer> node3 = new Node<Integer>();

  112. Node<Integer> node4 = new Node<Integer>();

  113. node1.data = 1;

  114. node2.data = 2;

  115. node3.data = 3;

  116. node4.data = 4;

  117. node1.next = node2;

  118. node2.next = node3;

  119. node3.next = node4;

  120. System.out.println(getTailK_modify(node1,11));

  121. }

  122. }

  123.  
  124. /**

  125. * 定义结点

  126. */

  127. class Node<T>{

  128. public T data;

  129. public Node<T> next;

  130. }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值