小王的Java刷题日记Day3
记录刷题过程,作为笔记和分享,坚持每天刷题,每天进步,编程语言为Java。
题目一:反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
例如:1->2->3->4->5 变为 5->4->3->2->1
思路一:头插法 时间复杂度O(n) 空间复杂度O(1)
1、我们需要将1先插入一个空节点的前边,即1->null。
2、其余节点依次头插法,将2插入到1前边,依次类推。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre=null;
//从该head节点开始,移动到下一个节点,直到到达链表末尾。
for(ListNode x=head;x!=null; x=x.next){
//对于原始链表中的每个节点,都会创建一个与原始节点(x.val)具有相同值的新节点。pre然后这个新节点被添加到链表的前面。这有效地颠倒了节点的顺序。
pre=new ListNode(x.val,pre);
}
return pre;
}
}
思路二:递归法 时间复杂度O(n) 空间复杂度O(n)--栈的层数
1、我们想让链表反转,那么第一轮出栈,head为5,head.next则为空,返回5 。
2、第二轮出栈,head为4,head.next为5,执行head.next.next=head也就是5.next=4, 把当前节点的子节点的子节点指向当前节点。此时链表为1->2->3->4<->5,由于4与5互相指向,所以此处要断开所以让4.next=null,那么此时链表为1->2->3->4<-5。
3、依次类推即可。
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}
题目二:环形链表
给你一个链表的头节点 head
,判断链表中是否有环。
思路一:双指针法 时间复杂度O(n) 空间复杂度O(1)
1、通过快慢指针,让慢指针指向头节点,快指针指向头节点的下一个节点。
2、若链表中存在环的话,那么快指针是提前进入环的,在某一时刻,快指针在环中一定可以追到慢指针。那么,我们依次为依据进行判断。
public class Solution {
public boolean hasCycle(ListNode 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){ //若快指针指向空时,说明没有环
return false;
}
slow=slow.next;
fast=fast.next.next;
}
return true;
}
}
思路二:哈希表 时间复杂度O(n) 空间复杂度O(n)
我们可以使用哈希表来存储所有已经访问过的节点。每次我们到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表即可。
public class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> seen = new HashSet<ListNode>(); // 用于存储已经遍历过的节点
while (head != null) {
if (!seen.add(head)) { //如果当前节点已经存在于集合中,说明存在环
return true;
}
head = head.next; //移动到下一节点,继续遍历
}
return false; //未发现有环
}
}