刷题学习

1、爬楼地,获取斐波那契数列。

使用递归得到斐波那契数列:(1,1,2,3,5,8,13 ……….每一项是前两项的和)
(1)、使用循环,从头往后找

  1. private static int printFibnachi01(int num) {
  2. if(num == 1){
  3. return 1;
  4. }else if(num == 2){
  5. return 1;
  6. }else {
  7. int pre = 1;
  8. int ppre = 1;
  9. int cur = 2;
  10. for (int i = 3; i <= num; i++) {
  11. cur = pre + ppre;
  12. ppre = pre;
  13. pre = cur;
  14. }
  15. return cur;
  16. }
  17. }

(2)、使用递归

  1. private static int printFibnachi(int num) {
  2. if(num == 1){
  3. return 1;
  4. }else if(num == 2){
  5. return 1;
  6. }else {
  7. return printFibnachi(num-1) + printFibnachi(num-2);
  8. }
  9. }

(3)、使用递归,上一种方法中会有大量重复计算,比如f(20)=f(19)+f(18),然后f(19)=f(18)+f(17), 而f(18)=f(17)+f(16),增加一个map用来存放已经找到的数,当需要找某一个值得时候,先去这个map中,如果找不到再来集合中找,这样可以节省栈内存,避免过度压栈

  1. private static Map<Integer,Integer> resultMap = new HashMap<>();
  2. private static int printFibnachi(int num) {
  3. if(num == 1){
  4. resultMap.put(1,1);
  5. return 1;
  6. }else if(num == 2){
  7. resultMap.put(2,1);
  8. return 1;
  9. }else {
  10. int pre = Objects.isNull(resultMap.get(num-1))?printFibnachi(num-1):resultMap.get(num-1);
  11. int ppre = Objects.isNull(resultMap.get(num-2))?printFibnachi(num-2):resultMap.get(num-2);
  12. resultMap.put(num,ppre+pre);
  13. return pre+ppre;
  14. }
  15. }

总结,简单使用递归,从原理上来说,易于理解,不过栈内存开销较大,如果递归层级太大,不适合实际使用。使用for循环可以避免,不过几个变量来回变换赋值得这个操作可能会有点绕。使用递归再定义一个集合来配合使用,可以有效结合。这种借助集合来暂存数据得思路,值得借鉴。顺便说一句,在实际开发中,程序中主要是使用各种集合来整理、处理各种数据,所以集合得使用必须熟练而灵活。

力扣还有一道爬楼梯得题和这个类似,只不过我还是没有理解,它是怎么转化成f(n) = f(n-1)+f(n-2)这个过程。
1:1
2:2(1+1,2)
3:3(1+1+1,1+2,2+1)
4:5(1+1+1+1,1+1+2,1+2+1,2+1+1,2+2)
5:8(1+1+1+1+1,1+1+1+2,1+1+2+1,1+2+1+1,1+2+2,2+1+1+1,2+1+2,2+2+1)

重新理解:假设有M(大于等于3)阶台阶,一共有f(m)中走法,每次只能走1个或2个台阶,那么这M阶可能的走法就包括两部分:前面+最后剩下1个台阶,前面+最后剩下2个台阶,所以所有的走法就等于这两种可能走法的和,那么转换过来也就是f(m-1)+f(m-2),那么同理f(m-1) = f(m-2)+f(m-3),如此使用递归的思想,直到m=2和m=1。

2、两数之和,给定一个整数,一个数组,从数组中找出两个整数,其和为目标整数,返回这两个整数的下标

解法一:两层for循环,挨个遍历

  1. private static int[] getTargetIndex01(int target, int[] arr) {
  2. int[] result = new int[2];
  3. for (int i = 0; i < arr.length - 1; i++) {
  4. for (int j = i+1; j < arr.length; j++) {
  5. if(arr[i] + arr[j] == target){
  6. result[0] = i;
  7. result[1] = j;
  8. return result;
  9. }
  10. }
  11. }
  12. return result;
  13. }

解法二:引入一个map,遍历的同时,进行判断。遍历数组,得到目标值和当前数的差值,拿这个差值去map中查,如果找不到,把当前值带下标(key是值,value下标)存入map,如果有,那么这个值和当前值就是要找的两个数。时间复杂度O(n)?应该会多一点吧,因为存入map和从map中获取也需要时间。数据量大的时候应该效果比较明显。
这个方法在于巧妙的引入一个外部结构来记录已经遍历过的数据,不需要重复遍历。这种思维需要好好学习。

  1. int target = 14;
  2. int[] arr = new int[]{2,5,2,6,4,8};
  3. int[] re = new int[2];
  4. Map<Integer,Integer> map = new HashMap<>();
  5. for (int i = 0; i < arr.length; i++) {
  6. int temp = target - arr[i];
  7. if(Objects.isNull(map.get(temp))){
  8. map.put(arr[i],i);
  9. }else {
  10. re[0] = map.get(temp);
  11. re[1] = i;
  12. }
  13. }

3、合并两个有序数组,合并之后元素都放在数组A中,并且仍然有序(数组A中有空余位置,比如{2,3,4,8,9,0,0,0})

解法一:将数组B中的元素放入数组A,然后直接利用Arrays.sort()的方法,sort()的底层使用的是快速排序,使用快速排序本身是挺快的,这种情况下使用,并不是最好,因为数组原本就是有序的,这样没有把这个有序的特点利用起来。

  1. int[] arrA = new int[]{2,3,4,8,9,0,0,0};
  2. int[] arrB = new int[]{1,4,5};
  3. //找到数组A最后一个有效元素
  4. int indexA = 0;
  5. for (int i = 0; i < arrA.length; i++) {
  6. if(arrA[i] == 0){
  7. indexA = i;
  8. break;
  9. }
  10. }
  11. //将B中的元素合并到A中
  12. for (int i = 0; i < arrB.length; i++) {
  13. arrA[indexA+i] = arrB[i];
  14. }
  15. Arrays.sort(arrA);
  16. for (int i : arrA) {
  17. System.out.print(i+" ");
  18. }

解法二:借助一个辅助数组,使用两个指针,分别对两个数组开始从头遍历,并进行比较,较小的元素放入新数组中,最后再把新数组的元素放入数组A中。需要注意的是,在第一个while循环结束时,两个数组中有一个的元素还没有完全放入新数组,所以还需要进行判断一下,把剩下的元素放入新数组

  1. int[] arrA = new int[]{2,3,4,8,9,0,0,0};
  2. int[] arrB = new int[]{1,4,5};
  3. int indexA = 0;
  4. for (int i = 0; i < arrA.length; i++) {
  5. if(arrA[i] == 0){
  6. indexA = i;
  7. break;
  8. }
  9. }
  10. //定义辅助数组和指针
  11. int[] temp = new int[arrA.length];
  12. int a = 0;
  13. int b = 0;
  14. int c = 0;
  15. while (a<=indexA-1 && b<=arrB.length-1){
  16. if(arrA[a]<=arrB[b]){
  17. temp[c++] = arrA[a++];
  18. }else {
  19. temp[c++] = arrB[b++];
  20. }
  21. }
  22. while (a<indexA){
  23. temp[c++] = arrA[a++];
  24. }
  25. while (b<arrB.length){
  26. temp[c++] = arrB[b++];
  27. }
  28. for (int i = 0; i < temp.length; i++) {
  29. arrA[i] = temp[i];
  30. }

解法三:解法二的时间复杂度有所提升,但是因为借助了一个辅助数组,所以空间复杂度就大了,这个题有一个特殊要求,就是排序后需要把元素放入数组A,所以可以借助这一点,因为数组A前面的元素是有序的,而后面都是0,后面0的个数又刚好等于数组B的个数。所以采用一种新思路,从后往前遍历两个数组,然后从大到小倒着排列所有的数,也是倒着放入数组A。因为数组A后面都是0,那么吧A和B比较之后较大的元素,依次放入。

  1. int[] arrA = new int[]{2,3,4,8,9,0,0,0};
  2. int[] arrB = new int[]{1,4,5};
  3. int indexA = 0;
  4. for (int i = 0; i < arrA.length; i++) {
  5. if(arrA[i] == 0){
  6. indexA = i;
  7. break;
  8. }
  9. }
  10. int a = indexA -1;
  11. int b = arrB.length -1;
  12. int c = arrA.length-1;
  13. int[] temp = new int[arrA.length];
  14. while (a>=0 && b>=0){
  15. if(arrA[a]>=arrB[b]){
  16. temp[c--] = arrA[a--];
  17. }else {
  18. temp[c--] = arrB[b--];
  19. }
  20. }
  21. while (a>=0){
  22. temp[c--] = arrA[a--];
  23. }
  24. while (b>=0){
  25. temp[c--] = arrB[b--];
  26. }
  27. for (int i = 0; i < temp.length; i++) {
  28. arrA[i] = temp[i];
  29. }

4、移动0,给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序

解法一

  1. private static void moveZeroes(int[] nums) {
  2. if (nums == null) {
  3. return;
  4. }
  5. int j = 0;
  6. for (int i = 0; i < nums.length; i++) {
  7. if(nums[i] != 0){
  8. nums[j] = nums[i];
  9. j++;
  10. }
  11. }
  12. for (int i=j;i<nums.length;i++){
  13. nums[i] = 0;
  14. }
  15. }

解法二:思想与上面类似,关键点还是在于使用两个指针分别指向0和非0元素

  1. private static void moveZeroes(int[] nums) {
  2. if (nums == null) {
  3. return;
  4. }
  5. int j = 0;
  6. for (int i = 0; i < nums.length; i++) {
  7. if (nums[i] != 0) {
  8. int tmp = nums[i];
  9. nums[i] = nums[j];
  10. nums[j++] = tmp;
  11. }
  12. }
  13. }

5、找出消失的数字。给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果

方法一:定义一个大小为N的辅助数组,元素为布尔类行,默认为false,
遍历数据,得到的元素,将这个值作为下标,更新对应辅助数组这个下标的元素状态为true
遍历辅助数组,元素为false的元素就是消失的数字,返回下标

  1. int[] arr = new int[]{1,4,2,4,8,8,8,8};
  2. //得到结果
  3. Object[] re = findLostNum(arr);
  4. for (Object o : re) {
  5. System.out.println(o);
  6. }
  7. //方法:
  8. private Object[] findLostNum(int[] arr) {
  9. boolean[] temp = new boolean[arr.length];
  10. for (boolean b : temp) {
  11. b = false;
  12. }
  13. for (int i : arr) {
  14. temp[i-1] = true;
  15. }
  16. List<Integer> re = new ArrayList<>();
  17. for (int i = 1; i < temp.length ; i++) {
  18. if(!temp[i-1]){
  19. re.add(i);
  20. }
  21. }
  22. return re.toArray();
  23. }

方法二:利用本数组,元素与下标的关系,遍历数组,得到每一个元素,
把这个元素的值当做下标,操作对应位置的元素,把这个位置的元素设置为负数,判断一个如果为正,就加个负号
遍历完成之后,元素仍然为正的位置下标值就是数组中没有的数字

  1. int[] arr = new int[]{1,4,2,4,8,8,8,8};
  2. //得到结果
  3. Object[] re = findLostNum(arr);
  4. for (Object o : re) {
  5. System.out.println(o);
  6. }
  7. //方法
  8. private Object[] findLostNum(int[] arr) {
  9. for (int i : arr) {
  10. int temp = i;
  11. if(i<0){
  12. temp = -i;
  13. }
  14. if(arr[temp-1] >0){
  15. arr[temp-1] = -arr[temp-1];
  16. }
  17. }
  18. List<Integer> re = new ArrayList<>();
  19. for (int i = 1; i < arr.length ; i++) {
  20. if(arr[i-1] > 0){
  21. re.add(i);
  22. }
  23. }
  24. return re.toArray();
  25. }

6、合并两个有序链表,合并完仍然有序

方法:

  1. private Node mergeLinkList(Node node14, Node node04) {
  2. //合并两个有序链表
  3. Node result = new Node();
  4. Node re = result;
  5. Node a = node04;
  6. Node b = node14;
  7. //循环比较
  8. while (a != null && b != null){
  9. if(a.getValue()>=b.getValue()){
  10. re.setNext(a);
  11. a = a.getNext();
  12. }else {
  13. re.setNext(b);
  14. b = b.getNext();
  15. }
  16. re = re.getNext();
  17. }
  18. //处理剩余节点
  19. if( a != null){
  20. re.setNext(a);
  21. }
  22. if(b != null){
  23. re.setNext(b);
  24. }
  25. return result.getNext();
  26. }

测试:

  1. //构造有序链表
  2. Node node01 = new Node(1,null);
  3. Node node02 = new Node(3,node01);
  4. Node node03 = new Node(4,node02);
  5. Node node04 = new Node(5,node03);
  6. Node node11 = new Node(5,null);
  7. Node node12 = new Node(5,node11);
  8. Node node13 = new Node(6,node12);
  9. Node node14 = new Node(7,node13);
  10. //调用方法
  11. Node node = mergeLinkList(node14, node04);
  12. //测试
  13. while (node != null){
  14. System.out.println(node.getValue());
  15. node = node.getNext();
  16. }

7、删除有序列表中的重复节点

方法:

  1. private Node deleteRepeatNode(Node node){
  2. if(node == null){
  3. return null;
  4. }
  5. //遍历链表节点,定义一个当前节点,如果当前节点的值与下一个节点的值相等,就直接将当前节点指向下一个节点的下一个节点
  6. Node cur = node;
  7. while (node != null){
  8. if(node.getValue().equals(node.getNext().getValue())){
  9. node.setNext(node.getNext().getNext());
  10. }
  11. }
  12. return cur;
  13. }

测试:

  1. void linkSortTest(){
  2. //构造有序链表
  3. Node node11 = new Node(5,null);
  4. Node node12 = new Node(5,node11);
  5. Node node13 = new Node(6,node12);
  6. Node node14 = new Node(6,node13);
  7. Node node15 = new Node(7,node14);
  8. Node result = deleteRepeatNode(node15);
  9. while (result != null){
  10. System.out.println(result.getValue());
  11. result = result.getNext();
  12. }
  13. }

这里的Node类中的属性修饰符使用了private,如果使用public修饰,其实就不需要get(),set()方法。通常这种方法应该是和Node类在同一个文件下,这样方便操作,这种方法也是类似于工具类的方法

8、环形列表,判断一个链表是否有环

方法:

  1. private Boolean cycle(Node node01) {
  2. if(node01 == null){
  3. return false;
  4. }
  5. Node slow = node01;
  6. Node fast = node01.next;
  7. while (slow.next != null && fast.next.next != null){
  8. if(slow == fast){
  9. return true;
  10. }
  11. slow = slow.next;
  12. fast = fast.next.next;
  13. }
  14. return false;
  15. }

测试:

  1. void linkSortTest(){
  2. //构造有序链表
  3. Node node01 = new Node(1,null);
  4. Node node02 = new Node(2,null);
  5. Node node03 = new Node(3,null);
  6. Node node04 = new Node(4,null);
  7. Node node05 = new Node(5,null);
  8. Node node06 = new Node(6,null);
  9. Node node07 = new Node(7,null);
  10. node01.next = node02;
  11. node02.next = node03;
  12. node03.next = node04;
  13. node04.next = node05;
  14. node05.next = node06;
  15. node06.next = node07;
  16. node07.next = node01;
  17. Boolean re = cycle(node01);
  18. System.out.println(re);
  19. }

9、找到环形列表的入口,如果没有环,返回null

方法:

  1. private Node findEntrence(Node head){
  2. if(head == null){
  3. return null;
  4. }
  5. Node slow = head;
  6. Node fast = head;
  7. while (slow != null && fast.next != null){
  8. slow = slow.next;
  9. fast = fast.next.next;
  10. if(slow == fast){
  11. slow = head;
  12. while (slow != fast){
  13. slow = slow.next;
  14. fast = fast.next;
  15. }
  16. return slow;
  17. }
  18. }
  19. return null;
  20. }

测试:

  1. void linkSortTest(){
  2. //构造有序链表
  3. Node node01 = new Node(1,null);
  4. Node node02 = new Node(2,null);
  5. Node node03 = new Node(3,null);
  6. Node node04 = new Node(4,null);
  7. Node node05 = new Node(5,null);
  8. Node node06 = new Node(6,null);
  9. Node node07 = new Node(7,null);
  10. node01.next = node02;
  11. node02.next = node03;
  12. node03.next = node04;
  13. node04.next = node05;
  14. node05.next = node06;
  15. node06.next = node07;
  16. node07.next = node01;
  17. System.out.println(findEntrence(node01).value);
  18. }

10、相交链表,给出两个链表, 找到他们相交的节点

方法:

  1. private Node findOverlapNode(Node node1, Node node2) {
  2. if(node1 == null || node2 == null){
  3. return null;
  4. }
  5. //计算两个列表长度
  6. int l1 = 0;
  7. int l2 = 0;
  8. Node n1 = node1;
  9. while (n1.next != null){
  10. l1++;
  11. n1 = n1.next;
  12. }
  13. Node n2 = node2;
  14. while (n2.next != null){
  15. l2++;
  16. n2 = n2.next;
  17. }
  18. //长链表跳过差值长度,短链表头结点开始
  19. if(l1 > l2){
  20. int n = l1 - l2;
  21. n1 = node1;
  22. for (int i = 0; i < n; i++) {
  23. n1 = n1.next;
  24. }
  25. n2 = node2;
  26. }else {
  27. int n = l2 - l1;
  28. n2 = node2;
  29. for (int i = 0; i < n; i++) {
  30. n2 = n2.next;
  31. }
  32. n1 = node1;
  33. }
  34. while (n1.next != null && n2.next != null){
  35. while ( n1 != n2){
  36. n1 = n1.next;
  37. n2 = n2.next;
  38. }
  39. return n1;
  40. }
  41. return null;
  42. // //使用双指针
  43. // Node n1 = node1;
  44. // Node n2 = node2;
  45. // while (n1 != n2){
  46. // n1 = n1.next == null ? node2 : n1.next;
  47. // n2 = n2.next == null ? node1 : n2.next;
  48. // }
  49. // return n1;
  50. // //引入一个hashMap
  51. // Set<Node> set = new HashSet<>();
  52. // Node n1 = node1;
  53. // while (n1.next != null){
  54. // Node node = n1;
  55. // set.add(node);
  56. // n1 = n1.next;
  57. // }
  58. // Node n2 = node2;
  59. // while (n2.next != null){
  60. // if(set.contains(n2)){
  61. // return n2;
  62. // }
  63. // n2 = n2.next;
  64. // }
  65. // return null;
  66. // //暴戾穷举
  67. // Node n1 = node1;
  68. // while (n1.next != null){
  69. // Node n2 = node2;
  70. // while (n2.next != null){
  71. // if(n1 == n2){
  72. // return n1;
  73. // }
  74. // n2 = n2.next;
  75. // }
  76. // n1 = n1.next;
  77. // }
  78. // return null;
  79. }

测试:

  1. void linkSortTest(){
  2. //构造有序链表
  3. Node node01 = new Node(1,null);
  4. Node node02 = new Node(2,null);
  5. Node node03 = new Node(3,null);
  6. Node node04 = new Node(4,null);
  7. Node node05 = new Node(5,null);
  8. Node node06 = new Node(6,null);
  9. Node node07 = new Node(7,null);
  10. Node node08 = new Node(8,null);
  11. Node node09 = new Node(9,null);
  12. Node node010 = new Node(10,null);
  13. Node node011 = new Node(11,null);
  14. Node node012 = new Node(12,null);
  15. node01.next = node02;
  16. node02.next = node03;
  17. node03.next = node04;
  18. node04.next = node05;
  19. node05.next = node06;
  20. node06.next = node07;
  21. // node07.next = node01;
  22. node07.next = null;
  23. node08.next = node09;
  24. node09.next = node010;
  25. node010.next = node011;
  26. node011.next = node012;
  27. node012.next = node03;
  28. Node re = findOverlapNode(node01,node08);
  29. System.out.println(re.value);
  30. }

11、反转链表

方法:

  1. private Node reverseLink(Node head) {
  2. if(head == null){
  3. return null;
  4. }
  5. //定义两个节点临时记录,cur pre
  6. Node cur = head;
  7. Node pre = null;
  8. while (cur.next != null){
  9. Node next = cur.next;
  10. cur.next = pre;
  11. pre = cur;
  12. cur = next;
  13. }
  14. //最后一个节点需要单独处理
  15. cur.next = pre;
  16. return cur;
  17. }

测试:

  1. void linkSortTest(){
  2. //构造有序链表
  3. Node node01 = new Node(1,null);
  4. Node node02 = new Node(2,null);
  5. Node node03 = new Node(3,null);
  6. Node node04 = new Node(4,null);
  7. Node node05 = new Node(5,null);
  8. Node node06 = new Node(6,null);
  9. Node node07 = new Node(7,null);
  10. node01.next = node02;
  11. node02.next = node03;
  12. node03.next = node04;
  13. node04.next = node05;
  14. node05.next = node06;
  15. node06.next = node07;
  16. node07.next = null;
  17. Node re = reverseLink(node01);
  18. while (re != null){
  19. System.out.println(re.value);
  20. re = re.next;
  21. }
  22. }

12、判断链表是否是回文链表

解法一:借助一个数组,遍历链表之后,把所有的值存入数组,然后使用两个指针分别从收尾开始遍历数组,对元素进行判断,直到相遇
方法:

  1. private static boolean palindrome01(Node head) {
  2. if(head == null){
  3. return false;
  4. }
  5. List<Integer> temp = new ArrayList<>();
  6. temp.add(head.value);
  7. Node node = head;
  8. while (node.next != null){
  9. node = node.next;
  10. temp.add(node.value);
  11. }
  12. int left = 0;
  13. int right = temp.size()-1;
  14. while (left<right){
  15. if(temp.get(left) != temp.get(right)){
  16. return false;
  17. }
  18. left++;
  19. right--;
  20. }
  21. return true;
  22. }

解法二:借用双指针,找到中间节点,然后把后半部分翻转,然后一次比较两个链表
方法:

  1. private static boolean palindrome002(Node head) {
  2. if(head == null){
  3. return false;
  4. }
  5. Node slow = head;
  6. Node fast = head;
  7. while (fast != null && fast.next != null){
  8. slow = slow.next;
  9. fast = fast.next.next;
  10. }
  11. if(fast != null){
  12. slow = slow.next;
  13. }
  14. Node temp = reverseLink(slow);
  15. slow = head;
  16. while (temp != null && slow != null){
  17. if(temp.value != slow.value){
  18. return false;
  19. }
  20. temp = temp.next;
  21. slow = slow.next;
  22. }
  23. return true;
  24. }

测试:

  1. public static void main(String[] args) {
  2. //回文链表 1235321 //构造有序链表
  3. Node node01 = new Node(1,null);
  4. Node node02 = new Node(2,null);
  5. Node node03 = new Node(3,null);
  6. Node node04 = new Node(4,null);
  7. Node node05 = new Node(3,null);
  8. Node node06 = new Node(2,null);
  9. Node node07 = new Node(1,null);
  10. node01.next = node02;
  11. node02.next = node03;
  12. node03.next = node04;
  13. node04.next = node05;
  14. node05.next = node06;
  15. node06.next = node07;
  16. node07.next = null;
  17. //解法一:借助一个数组,遍历链表之后,把所有的值存入数组,然后使用两个指针分别从收尾开始遍历数组,对元素进行判断,直到相遇
  18. boolean palindrome01 = palindrome01(node01);
  19. System.out.println(palindrome01);
  20. //解法二:借用双指针,找到中间节点,然后把后半部分翻转,然后一次比较两个链表
  21. boolean palindrome02 = palindrome002(node01);
  22. System.out.println(palindrome02);
  23. }

13、找到链表的中间节点

上一题中间的一部分内容,快指针走到结尾,慢指针刚好到中间

  1. Node slow = head;
  2. Node fast = head;
  3. while (fast != null && fast.next != null){
  4. slow = slow.next;
  5. fast = fast.next.next;
  6. }

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

找到倒数第K个节点,先得到所有节点数n,倒数第K个,也就是正数第n-K+1。(还有一个方法,是引入一个列表或者hashMap,遍历节点的时候把节点数据存进去,然后在取数据)
方法:

  1. private static Node findKNode(Node head, Integer k) {
  2. if(head == null){
  3. return null;
  4. }
  5. Integer n = 0;
  6. Node node = head;
  7. while (node.next != null){
  8. n++;
  9. node = node.next;
  10. }
  11. if(n < k){
  12. return null;
  13. }
  14. node = head;
  15. for (int i = 0; i < n-k+1; i++) {
  16. node = node.next;
  17. }
  18. return node;
  19. }