package day09;
//合并两个有序链表
import java.util.ArrayList;
import java.util.List;
public class MergeTwoLists {
public static void main(String[] args) {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(2);
ListNode node4 = new ListNode(1);
ListNode node5 = new ListNode(3);
ListNode node6 = new ListNode(4);
//测试合并
/*node1.next = node2;
node2.next = node3;// 1->2->4
node4.next = node5;
node5.next = node6;//1->3->4
ListNode newList = mergeTwoLists(node1, node4);
System.out.println(newList);*/
//测试回文链表
node1.next = node2;//1->2 false
//node2.next = node3;
// node3.next = node4;//1->2->2->1 true
//测试思路1
//boolean res = isPalindrome(node1);
//System.out.println(res);
MergeTwoLists test = new MergeTwoLists();
//测试思路2
//boolean res = test.isPalindrome02(node1);
// System.out.println(res);
//测试思路3
boolean res = test.isPalindromeList(node1);
System.out.println(res);
}
//输入:1->2->4, 1->3->4
//输出:1->1->2->3->4->4
public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode tmp1 = l1;
ListNode tmp2 = l2;
ListNode newHead = new ListNode(-1);//新链表的头节点
ListNode cur = newHead;//总是指向新链表的最后一个结点,方便插入新结点
while (tmp1 != null && tmp2 != null) {
if (tmp1.val <= tmp2.val) {
cur.next = tmp1;
tmp1 = tmp1.next;//这两条语句使得当前需要插入的结点插入到新链表末尾并与l1断链
} else {
cur.next = tmp2;
tmp2 = tmp2.next;// 这两条语句使得当前需要插入的结点插入到新链表末尾并与l2断链
}
cur = cur.next;//总是指向新链表的最后一个结点,方便插入新结点
}
//将非空的那一个链表 tmp1或者tmp2 与新链表的末尾 连接
cur.next = (tmp1 != null)? tmp1:tmp2;
//头结点是我们用来方便插入的
return newHead.next;
}
//判断一个链表是否是回文链表
//输入: 1->2
//输出: false
//输入: 1->2->2->1
//输出: true
//思路1:直接将链表的每个数字取出来放到列表中,然后使用双指针法判断是否为回文链表
//时间复杂度O(n),空间复杂度为O(n)
public static boolean isPalindrome(ListNode head) {
if (head == null) {
return true;
}
ListNode tmp = head;
List<Integer> vals = new ArrayList<>();
while (tmp != null) {
vals.add(tmp.val);
tmp = tmp.next;
}
int i = 0;
int j = vals.size() - 1;
while (i < j) {
if (vals.get(i).equals(vals.get(j))) {// 注意!!!这里get方法返回的是Integer类型,不能直接用==比较
i ++;
j --;
} else {
return false;
}
}
return true;
}
//思路2:使用递归,定义一个curNode递归指向链表尾部,一个frontNode指向链表头部
//递归回溯时(也就是curNode到达链表末尾时),比较curNode.val是否等于frontNode.val
//相等-->frontNode指向下一个结点,curNode继续 回溯
//不相等则返回false
ListNode frontNode;
public boolean recursionCheck(ListNode curNode) {
//当curNode指向链表最后一个结点时,curNode.next == null,不在进入此 if 语句,跳到程序末尾return true
//这是回文最基本的情况,当为空时,是回文链表
if (curNode != null) {
//curNode递归指向链表尾部
if (!recursionCheck(curNode.next)) {
return false;
}
//递归回溯时(也就是curNode到达链表末尾时),比较curNode.val是否等于frontNode.val
//不相等则返回false
if (frontNode.val != curNode.val) {
return false;
}
//相等-->frontNode指向下一个结点,curNode继续 回溯
frontNode = frontNode.next;
}
return true;
}
public boolean isPalindrome02(ListNode head) {
if (head == null) {
return true;
}
frontNode = head;//frontNode指向链表头部
return recursionCheck(head);//curNode递归指向链表尾部
}
//思路3:我们希望空间复杂度为O(1), 这时我们只能在链表本身上比较,回文就是前面一半 和 后面一半相同
//容易想到,找到链表前半部分的尾结点,反转后半部分的链表,然后判断是否为回文
//回复链表为原样
public boolean isPalindromeList(ListNode head) {
if (head == null) {
return true;
}
ListNode firstHalfEndNode = endOfFirstHalf(head);
ListNode secondHalfStart = reverseList(firstHalfEndNode.next);
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while (result && p2 != null) {
if (p1.val == p2.val) {
p1 = p1.next;
p2 = p2.next;
} else {
result = false;
}
}
//还原链表
firstHalfEndNode.next = reverseList(secondHalfStart);
//返回结果
return result;
}
//找到前半部分的尾结点,使用快慢指针若链表有奇数个节点,则中间的节点应该看作是前半部分。
public ListNode endOfFirstHalf(ListNode head) {
ListNode fast = head;
ListNode slow = head;
//快指针走两步,慢指针走一步,快指针到达末尾时,慢指针刚好是前半部分的尾结点
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
//反转后半部分的结点
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode tmpNext = cur.next;
cur.next = pre;
pre = cur;
cur = tmpNext;
}
return pre;
}
}
class ListNode {
int val;
ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
@Override
public String toString() {
return "ListNode{" +
"val=" + val +
", next=" + next +
'}';
}
}
判断一个链表是否为回文链表的三种思路及JAVA代码实现
最新推荐文章于 2022-10-17 17:55:14 发布