【面试必备】手撕代码,你怕不怕? (6)

这是一道很经典的题,不仅考你对链表的理解,而且还有一些细节(例如正确性判断/ 测试用例)需要你从代码层面去展现,下面我们给出两段代码,读者可以自行去比较,我只是提供一个思路;

思路一:使用一个 Node 不断链接

这是最经典的算法,也是需要我们牢牢掌握的方法,最重要的还是理解 while() 循环中的过程:

public ListNode reverseList(ListNode head) { // 正确性判断 if (null == head || null == head.next) { return head; } ListNode pre = null; while (null != head) { ListNode temp = head; head = head.next; temp.next = pre; pre = temp; } return pre; } 思路二:反转元素值然后重新赋给 Node

这是一个很简单的思路,比上个思路要多遍历一遍链表,但是好处是简单,思路清晰,实现起来容易,emm,像这一类问题我觉得另一个比较重要的就是举一反三的能力吧,在这里我只提供两个思路,其实还有很多种实现方法,当然也别忘了细节的东西~

public ListNode reverseList(ListNode head) { // 1.正确性判断 if (null == head || null == head.next) { return head; } // 2.遍历链表head并将结果保存在List集合中 List<ListNode> list = new LinkedList(); ListNode tempNode = head; while (null != tempNode) { list.insert(tempNode.val); tempNode = tempNode.next; } // end while:遍历完了链表并将结果保存在了List集合中 // 3.反转集合,并将值依次复制给链表 Collections.reverse(list); tempNode = head; while (null != tempNode) { tempNode.val = list.remove(0); tempNode = tempNode.next; } return head; } 2.合并两个有序链表

问题描述:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的;

同样的经典算法,需要掌握:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null) { return l2; } if (l2 == null) { return l1; } ListNode head = null; if (l1.val < l2.val) { head = l1; head.next = mergeTwoLists(l1.next, l2); } else { head = l2; head.next = mergeTwoLists(l1, l2.next); } return head; }

这道题也是 LeetCode 上的一道题,我当时的做法是下面这样的,虽然看起来代码量多了不少而且看起来蠢蠢的..但是经过 LeetCode 测试,甚至比上面的实现要快上那么 2ms,特别提醒:下面的代码只是用作一个思路的参考,着重掌握上面的代码

public ListNode mergeTwoLists(ListNode l1, ListNode l2) { // 定义一个虚拟头结点方便遍历 ListNode dummyHead = new ListNode(-1); dummyHead.next = l1; ListNode pre = dummyHead; // 遍历l1链表 int len1 = 0; while (null != pre.next) { len1++; pre = pre.next; } int[] nums1 = new int[len1]; // 保存l1链表的数据 pre = dummyHead; for (int i = 0; i < len1; i++) { nums1[i] = pre.next.val; pre = pre.next; } // 遍历l2链表 int len2 = 0; dummyHead.next = l2; pre = dummyHead; while (null != pre.next) { len2++; pre = pre.next; } int[] nums2 = new int[len2]; // 保存l2链表的数据 pre = dummyHead; for (int i = 0; i < len2; i++) { nums2[i] = pre.next.val; pre = pre.next; } int[] nums = new int[len1 + len2]; // 将两个链表的数据整合并排序 System.arraycopy(nums1, 0, nums, 0, len1); System.arraycopy(nums2, 0, nums, len1, len2); Arrays.sort(nums); // 拼接一个链表 ListNode dummy = new ListNode(-1); pre = dummy; for (int i = 0; i < nums.length; i++) { ListNode node = new ListNode(nums[i]); pre.next = node; pre = pre.next; } return dummy.next; } 3.两个链表的第一个公共结点

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdpfy.html