环形链表
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null) return false;
ListNode fast = head.next;
ListNode slow = head;
while(fast != slow){
if(fast == null || fast.next == null) return false;
fast = fast.next.next;
slow = slow.next;
}
return true;
}
public boolean hasCycle1(ListNode head) {
Set<ListNode> nodesSeen = new HashSet<>();
while (head != null) {
if (nodesSeen.contains(head)) {
return true;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return false;
}
环形链表II
7<-6<- 5
| ^
| |
0->1->2->3->4
[-----]
我们设置快慢两个指针,fast, slow fast一次前进两步,
slow一次前进一步,
设a为第一个节点到入环节点的距离。 a=[0->2]
设b为入环口到相遇点的距离。b=[2->6]
设c为相遇点到入环口的距离。c=[6->2]
当fast,和slow相遇的时候,fast经过的节点是slow的两倍,设slow经过的节点数为S
根据上面的设置 可知 S=a+b ,2S=a+b+c+b,可知 a=c,此时让slow回到第一个节点,
fast处于第一次相遇的节点,此时slow从第一个节点出发,因为a=c,所以fast,
和slow会在入环口第二次相遇,得到要求的节点。
----------------------------------------------------------------
public ListNode detectCycle(ListNode head)
{
if(head==null)
return head;
// 步骤一:使用快慢指针判断链表是否有环,必须快慢指针为同一起跑线
ListNode fast = head, slow = head;
boolean hasCycle = false;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast =fast.next.next;
if (slow == fast) {
hasCycle = true;
break;
}
}
// 步骤二:若有环,找到入环开始的节点
if (hasCycle)
{
ListNode q = head;
while (slow!= q)
{
slow = slow.next;
q = q.next;
}
return q;
} else
return null;
}
返回链表倒数第n个节点
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode quick=head;
ListNode slow=head;
while(k>0){
quick=quick.next;
k--;
}
while(quick!=null)
{
quick=quick.next;
slow=slow.next;
}
return slow;
}
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null||k<=0)
{
return null;
}
ListNode n1=head,n2=head;
int count=0;
int index=k;
while(n1!=null)
{
n1=n1.next;
count++;
if(k<1)
{
n2=n2.next;
}
k--;
}
if(count<index)
{
return null;
}
return n2;
删除链表倒数第n个节点
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode temp=new ListNode(0);
temp.next=head;
ListNode quick=temp;
ListNode slow=temp;
while(n>0)
{
quick=quick.next;
n--;
}
while (quick.next!=null)
{
quick=quick.next;
slow=slow.next;
}
slow.next=slow.next.next;
return temp.next;
}
合并两个有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null)
{
return l2;
}
if(l2==null)
{
return l1;
}
ListNode dhead=new ListNode(0);
dhead.next=l1.val<=l2.val?l1:l2;
if(dhead.next==l1)
{
l1=l1.next;
}
else {
l2=l2.next;
}
ListNode temp=dhead.next;
while (l1!=null&&l2!=null)
{
if(l1.val<=l2.val)
{
temp.next=l1;
temp=temp.next;
l1=l1.next;
}
else {
temp.next = l2;
temp=temp.next;
l2 = l2.next;
}
}
temp.next=l1==null?l2:l1;
return dhead.next;
}
反转链表
@迭代
public ListNode reverseList(ListNode head) {
ListNode pre = null, cur = head, next = null;
while(cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
@递归
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode node = reverseList(head.next);
head.next.next = head;
head.next = null;
return node;
}
回文链表
@双指针
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null)
{
return true;
}
ListNode slow=head,quick=head,pre=null;
//1.快慢指针,找到链表的中点。
while(quick!=null&&quick.next!=null)
{
slow=slow.next;
quick=quick.next.next;
}
//2.将slow之后链表反转
while(slow!=null)
{
ListNode next=slow.next;
slow.next=pre;
pre=slow;
slow=next;
}
//3.前后链表进行比较,注意若为奇数链表,多1一个节点,然而并不影响判断回文
while (head!=null&&pre!=null)
{
if(head.val!=pre.val)
return false;
head=head.next;
pre=pre.next;
}
return true;
}
public boolean isPalindrome1(ListNode head) {
// 要实现 O(n) 的时间复杂度和 O(1) 的空间复杂度,需要翻转后半部分
if (head == null || head.next == null) {
return true;
}
ListNode fast = head;
ListNode slow = head;
// 根据快慢指针,找到链表的中点
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
slow = reverse(slow.next);
while(slow != null) {
if (head.val != slow.val) {
return false;
}
head = head.next;
slow = slow.next;
}
return true;
}
private ListNode reverse(ListNode head){
// 递归到最后一个节点,返回新的新的头结点
if (head.next == null) {
return head;
}
ListNode newHead = reverse(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
//单链表检查回文串的难点就在于,只能沿一个方便遍历,双指针无法进行
//于是我们就想到可以借用一个辅助数组,将链表节点拷贝到数组中,
// 然后再数组中双指针检查,空间复杂度为O(n),时间复杂度O(n)
public boolean isPalindrome2(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ArrayList<Integer> list = new ArrayList<>();
ListNode cur = head;
// 1、拷贝到数组
while (cur != null) {
list.add(cur.val);
cur = cur.next;
}
int lo = 0; // 头指针
int hi = list.size() - 1; // 尾指针
// 2、双指针检查
while (lo <= hi) {
if (!list.get(lo).equals(list.get(hi))) {
return false;
}
lo++;
hi--;
}
return true;
}
public boolean isPalindrome3(ListNode head) {
Stack<ListNode> s=new Stack();
ListNode p=head;
while(p!=null)
{
s.push(p);
p=p.next;
}
p=head;
while(!s.isEmpty())
{
if(s.peek().val!=p.val)
{
return false;
}
s.pop();
p=p.next;
}
return true;
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode h1 = headA, h2 = headB;
while (h1 != h2) {
h1 = h1 == null ? headB : h1.next;
h2 = h2 == null ? headA : h2.next;
}
return h1;
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int len1=0;
int len2=0;
ListNode n1=headA;
ListNode n2=headB;
while(n1!=null)
{
n1=n1.next;
len1++;
}
while(n2!=null)
{
n2=n2.next;
len2++;
}
int cha=len2-len1;
if(cha>0)
{
while(cha>0)
{
cha--;
headB=headB.next;
}
}
if(cha<0)
{
while(cha<0)
{
cha++;
headA=headA.next;
}
}
while(headA!=null&&headB!=null)
{
if(headA==headB)
{
return headA;
}
headA=headA.next;
headB=headB.next;
}
return null;
}
删除排序链表中的重复元素
public ListNode deleteDuplicates(ListNode head) {
ListNode n=head;
while(n!=null&&n.next!=null){
if(n.val==n.next.val)
{
ListNode cur=n;
while(n.val==n.next.val)
{
n=n.next;
if(n.next==null)
{
break;
}
}
cur.next=n.next;
}
n=n.next;
}
return head;
}
两两交换链表中的节点
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode next = head.next;
head.next = swapPairs(next.next);
next.next = head;
return next;
}
public ListNode swapPairs(ListNode head) {
ListNode temphead=new ListNode(0);
temphead.next=digui(head);
return temphead.next;
}
public ListNode digui(ListNode temp)
{
if(temp==null)
return null ;
ListNode one=temp;
ListNode two=temp.next;
if(two!=null){
one.next=digui(two.next);
}
else{
one.next=null;
}
if(two!=null)
{
two.next=one;
return two;
}
else{
return one;
}
}
public ListNode swapPairs(ListNode head) {
if(head==null) {
return null;
}
ListNode n1=head;
ListNode n2=head.next;
if(n2==null) {
return n1;
}
ListNode x=new ListNode(0);
x.next=n2;
while(n1!=null&&n2!=null)
{
n1.next=n2.next;
ListNode temp=n1;
n2.next=n1;
n1=n1.next;
if(n1!=null) {
n2=n1.next;
} else {
n2=null;
}if(n2==null) {
temp.next=n1;
} else {
temp.next=n2;
}
}
return x.next;
}