文章目录
前言
本篇博客我们继续看链表笔试题第三期
一、Leetcode–234回文链表
1.题目描述
2.思路讲解
1.此时我们可以开辟一个新的链表,新链表的节点恰好是原链表的反转,然后我们同步开始遍历这两个链表,若发现有一个值不相等,就不是回文链表
2.本题 还有一个进阶解法
题目要求使用O(n)的时间复杂度和O(1)的空间复杂度解决此问题,这就表示不能再创建新的链表,那我们就在原链表的基础上反转一半链表,再让两部分链表同时遍历
3.代码实现
3.1创建新链表
//1.反转链表
public ListNode reverseList(ListNode head) {
ListNode dummyHead = new ListNode();
while (head != null){
ListNode note = new ListNode(head.val);
note.next = dummyHead.next;
dummyHead.next = note;
head = head.next;
}
return dummyHead.next;
}
//判断是否是回文链表
public boolean isPalindrome(ListNode head) {
ListNode newLink = reverseList(head);
while (head != null){
if (head.val != newLink.val){
return false;
}
head = head.next;
newLink = newLink.next;
}
return true;
}
3.2反转一半原链表
//判断是否是回文链表
public boolean isPalindrome(ListNode head) {
ListNode middleIndex = middleNode(head);
ListNode newLink = reverseList(middleIndex);
while (newLink != null){
if (head.val != newLink.val){
return false;
}
head = head.next;
newLink = newLink.next;
}
return true;
}
//1.找中间结点
public ListNode middleNode(ListNode head) {
if (head == null || head.next == null){
return head;
}
ListNode fast = head;
ListNode low = head;
while (fast != null && fast.next != null){
fast = fast.next.next;
low = low.next;
}
return low;
}
//反转链表
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null){
return head;
}
ListNode newHead = new ListNode();
ListNode node = head.next;
newHead = reverseList(head.next);
node.next = head;
head.next = null;
return newHead;
}
二、Leetcode–21.合并两个有序链表
1.题目描述
2.思路讲解
1.通过读题,我们知道新链表是通过给定的两个链表的结点拼接组成的,表示没有创建新的结点,所以空间复杂度是O(1),题目要求拼接后的链表也是升序链表,所以我们可以创建一个虚拟头结点,然后遍历两个给定的链表l1和l2
当l1和l2都不为空时,遍历两个链表,取最小值尾插如虚拟头结点之后,此时还得引入一个新的引用tail,表示当前新链表的尾结点
(1).首先当l1和l2不为空的时候,遍历这两个链表
若l1.val <= l2.val,就把当前l1拼接到新链表的尾部,l1继续向后移动
反之,将l2拼接到新链表的尾部,l2继续向后移动
(2).当某个子链表为空,剩下的链表全部拼接到新链表的尾部
(3).返回dummyHead.next即可
2.本题还可以使用递归,我们看一下这个函数的语义
传入两个排序链表,就能把这两个链表合并为一个大的排序链表,返回拼接后头结点
3.代码实现
3.1迭代
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null){
return list2;
}
if (list2 == null){
return list1;
}
ListNode dummyHead = new ListNode();
ListNode tail = dummyHead;
while (list1 != null && list2 != null){
if (list1.val <= list2.val){
tail.next = list1;
tail = list1;
list1 = list1.next;
}else{
tail.next = list2;
tail = list2;
list2 = list2.next;
}
}if (list1 == null){
tail.next = list2;
}
if (list2 == null){
tail.next = list1;
}
return dummyHead.next;
}
3.2递归写法
/**
* 传入两个排序链表,就能把这两个链表合并为一个大的排序链表,返回拼接后头结点
* @param list1
* @param list2
* @return
*/
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null){
return list2;
}
if (list2 == null){
return list1;
}
if (list1.val <= list2.val){
list1.next = mergeTwoLists(list1.next,list2);
return list1;
}else{
list2.next = mergeTwoLists(list1,list2.next);
return list2;
}
}
三、Leetcode–面试题02.04.分割链表
1.题目描述
2.思路讲解
本题的思路和上一题合并链表的思路相似
1.我们可以创建两个新的链表,新链表就是由原链表的结点组成的,一个链表smallHead存放小于x的结点,一个链表存bigHead放大于等于x的结点
2.然后将bigHead.nex拼接到smallTail之后(smallTail.next = bigHead.next)
3.返还smallHead.next即可
3.代码实现
public ListNode partition(ListNode head, int x) {
if (head == null || head.next == null){
return head;
}
ListNode smallHead = new ListNode();
ListNode smallTail = smallHead;
ListNode bigHead = new ListNode();
ListNode bigTail = bigHead;
while (head != null){
if (head.val < x){
smallTail.next = head;
smallTail = head;
}else{
bigTail.next = head;
bigTail = head;
}
head = head.next;
}
bigTail.next = null;
smallTail.next = bigHead.next;
return smallHead.next;
}