链表是个线性数据结构
由零个或多个数据元素组成的有限序列
第一个元素无前驱,最后一个元素没有后继,其余元素一个前驱一个后继
LeetCode 160、 找出两个链表的交点
本题中要找出两条链表的交点,首先要知道链表的特性,下一个节点的位置只能由上一个节点来确定,所以不能直接确定某个值得特定的位置,因此本题可以采用两轮循环来确定交点的位置,分别同时从A,B 两个链表的头结点开始遍历,遍历完之后,再从赢一个节点开始遍历这样在第二轮是会在交点处相遇。
第一种方法采用双指针的方法。
这个方法有几个注意的地方。首先,本题要求找出相交的点,如果找不到的话要返回null,首先两个链表从头开始遍历,而遍历结束的要求就是两个节点的值相同代表是同一个节点,采用三目运算符正好可以解决这个问题,采用if语句的话就打不到这个要求,而且这里的比较条件需要注意的,cur1 == null,而不是cur1.next == null,这里很关键,如果写成cur1.next == null,那么遍历到末尾会直接到另一个链表的表头,一直循环下去,这样的话如果没有交点的话则会一直循环下去四个死循环,就达不到题目的要求了,因此需要注意。而cur1 == null 如果遍历到末尾会奖励一个null节点,这样两轮之后必定同时到达相交的节点,即使没有相交的节点那么会同时到达最后的null节点处,并且直接返回该节点正好是null。符合题目要求。
//双指针
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) return null;
ListNode cur1 = headA;
ListNode cur2 = headB;
while(cur1 != cur2){
cur1 = (cur1 == null) ? headB : cur1.next;
cur2 = (cur2 == null) ? headA : cur2.next;
}
return cur1;
}
}
第二种方法采用哈希表,现将A链表遍历放入哈希表中,在从头开始遍历B链表查看哈希表总是否有存在的元素,如果有就返回这个元素,如果没有就返回null。
//哈希表法
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSet<ListNode> set = new HashSet<>();
ListNode cur = headA;
while(cur != null){
set.add(cur);
cur = cur.next;
}
ListNode temp = headB;
while(temp != null){
if(set.contains(temp)){
return temp;
}
temp = temp.next;
}
return null;
}
}
206、反转链表
反转一个单链表。
分析:反转链表即为将链表倒过来,但是考虑到后一个节点只能由前一个节点确定,所以要想达到翻转链表的效果,则需要有三个相邻的节点的位置,令cur.next.next = cur,与此同时一定要记录cur.next.next的位置,因为一旦执行上边的命令之后就不再可以通过cur.next来寻找cur.next.next了,因为已经指向了cur了。
第二种方法就是一直遍历到链表的末尾从最后开始反转这样就不用了记录后边的地址了。就是采用递归的方法。
class Solution{
public ListNode reverseList(ListNode head){
ListNode cur = null;
ListNode pre = head;
while(pre != null){
ListNode temp = pre.next;
pre.next = cur;
cur = pre;
pre = temp;
}
return cur;
}
}
递归法
递归的临界条件是遍历到最后一个节点,这是因为需要记录反转后的第一个节点的位置,如果遍历到倒数第二个节点就结束了,虽然可以达到翻转的效果但是,反转后的头结点会丢失掉,要明白翻转的本质就是cur.next.next = cur, 根据递归函数构造的不同,程序会有差异。
class Solution{
public ListNode reverseList(ListNode head){
if(head == null || head.next == null) return head;
ListNode temp = reerseList(head.next);
head.next.next = head;
head.next = null
return temp;
}
}
21、合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
class Solution{
public ListNode mergeTwoLists(ListNode l1, ListNode l2){
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
if(l1.val <= l2.val){
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}else{
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}