题库
一、环形链表
给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回 true 。 否则,返回 false 。
原题
1.哈希表解法
建立HashSet集合,利用其存储元素不可重复的特性,在遍历链表时把元素加进集合里,若加入失败,则证明集合里已有该元素,则链表有环。
代码如下:
Set<ListNode> s = new HashSet<ListNode>();
while(head != null) {
if(!s.add(head)) {
return true;
}
head = head.next;
}
return false;
2.快慢指针解法(花费时间更少)
建立快和慢两个指针,快指针指向 head.next 且每次走两步,慢指针指向 head 且每次走一步,若链表有环,则快指针会追上慢指针。
代码如下:
if(head == null || head.next == null)
return false;
ListNode slow = head;
ListNode fast = head.next;
while(slow != fast) {
if(fast == null || fast.next == null)//右边的条件是为了避免fast指针恰好超过slow指针一个位置
return false;
slow = slow.next;
fast = fast.next.next;
}
return true;
二、合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
原题
双指针解法
建立head和row两个指针,head作为新链表的头部保持不变,row作为尾部随着对两个链表的遍历而变化。
代码如下:
if(list1 == null)
return list2;
if(list2 == null)
return list1;
ListNode head = new ListNode();
ListNode row = head;
while(list1 != null && list2 != null) {
if(list1.val > list2.val) {
row.next = list2;
row = row.next;
list2 = list2.next;
}else {
row.next = list1;
row = row.next;
list1 = list1.next;
}
}
if(list1 == null)
row.next = list2;
if(list2 == null)
row.next = list1;
return head.next;
三、移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。原题
指针、节点结合解法
建立一个节点和指针,节点作为新链表的头部保持不变,指针作为尾部随着对老链表的遍历而改变。
代码如下:
ListNode pre = new ListNode(0);
pre.next = head;
ListNode next = pre;
while(next.next != null) {
if(next.next.val == val)
next.next = next.next.next;
else
next = next.next;
}
return pre.next;
总结
经过今天这几道题,我明白结点要用new来分配空间,指针只要定义就行。