160. 相交链表
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//让2个指针走一样的距离,消除步行差,那就一定可以一起走到相交点
//链表A: a+c, 链表B : b+c. a+c+b = b+c+a 。则会在公共处c起点相遇。
//若不相交,a+c+b+c = b+c+a+c 。因此相遇处是NULL
//边界条件判断
if(headA==null||headB== null) return null;
ListNode cur_a =headA,cur_b =headB;
while(cur_a!=cur_b)
{
if(cur_a!=null)
cur_a=cur_a.next;
else
cur_a=headB;
if(cur_b!=null)
cur_b=cur_b.next;
else
cur_b=headA;
}
return cur_b;
}
}
206. 反转链表
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null) return null;
ListNode pre = null;
ListNode cur = head;
while(cur!=null)
{
ListNode latter = cur.next;
cur.next=pre;
//更新下一轮状态
pre=cur;
cur=latter;
}
return pre;
}
}
234. 回文链表
class Solution {
public boolean isPalindrome(ListNode head) {
//回文链表 第一思路双指针
//把值存到数组,用双指针
ListNode cur= head;
List<Integer> arr = new ArrayList<>();
while(cur!=null)
{
arr.add(cur.val);
cur=cur.next;
}
int front =0;
int end=arr.size()-1;
while(front<end)
{
if(!(arr.get(front).equals(arr.get(end))))
return false;
front++;
end--;
}
return true;
}
}
141. 环形链表
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null||head.next==null) return false;
//当一个链表有环时,快慢指针都会陷入环中进行无限次移动,
//然后变成了追及问题。想象一下在操场跑步的场景,只要一直跑下去,快的总会追上慢的
ListNode slow =head;
ListNode fast = head.next;//不能fast也等于head,不然while循环都进不去
while(fast!=slow)
{
if(fast==null||fast.next==null) return false;
slow=slow.next;
fast=fast.next.next;
}
return true;
}
}
142. 环形链表 II
public class Solution {
public ListNode detectCycle(ListNode head) {
//寻找环入口---双指针
//龟兔赛跑,如果存在环,fast指针肯定能追上slow,与之相遇
//第一次相遇 distance: fast=2low fast比slow多走n个环
//fast-slow =nb(b为环长度) slow=nb fast =2nb
//环入口为a+nb,即slow再走a步
//如何再走a步 fast回起点 同时一步步走再相遇即是环入口
//if(head==null||head.next==null) return null;
ListNode fast=head;
ListNode slow=head;
while(true)
{
if(fast==null||fast.next==null) return null;
slow=slow.next;
fast=fast.next.next;
if(fast==slow) break;
}
//第一次相遇完毕
//再让slow走a步
fast=head;
while(true)
{
if(fast==slow) break;
slow=slow.next;
fast=fast.next;
//if(fast==slow) break;
}
return slow;
}
}
143. 重排链表
class Solution {
public void reorderList(ListNode head) {
//利用线性表存储该链表,
//然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。
ArrayList<ListNode> list = new ArrayList<>();
ListNode cur = head;
while(cur!=null)
{
list.add(cur);
cur=cur.next;
}
int i =0,j=list.size()-1;
while(i<j)
{
list.get(i).next=list.get(j);
i++;
list.get(j).next=list.get(i);
j--;
}
list.get(i).next=null;
}
}
21. 合并两个有序链表
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode dummy =new ListNode(-1);
ListNode pre = dummy;
ListNode l1=list1,l2=list2;
if(l1==null) return l2;
if(l2==null) return l1;
while(l1!=null&&l2!=null)
{
if(l1.val<l2.val)
{
pre.next=l1;
l1=l1.next;
}
else
{
pre.next=l2;
l2=l2.next;
}
pre=pre.next;
}
pre.next=(l1==null)?l2:l1;
return dummy.next;
}
}
2. 两数相加
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1);
ListNode pre =dummy;
int num1,num2,carry=0;
//int count=1;
while(l1!=null||l2!=null)
{
num1=(l1==null)?0:l1.val;
num2=(l2==null)?0:l2.val;
int num =(num1+num2+carry)%10;
carry=(num1+num2+carry)/10;
pre.next=new ListNode(num);
pre=pre.next;
if(l1!=null)
l1=l1.next;
if(l2!=null)
l2=l2.next;
}
if(carry==1)
pre.next= new ListNode(carry);
return dummy.next;
}
}
19. 删除链表的倒数第 N 个结点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//经典双指针
ListNode dummy =new ListNode(-1,head);
//dummy.next=head;
if(head==null) return null;
ListNode slow=dummy,fast=dummy;
for(int i=0;i<n;i++)
{
fast=fast.next;
}
while(fast.next!=null)
{
slow=slow.next;
fast=fast.next;
}
slow.next=slow.next.next;
return dummy.next;
}
}
24. 两两交换链表中的节点
class Solution {
public ListNode swapPairs(ListNode head) {
//递归实现
//递归终止条件
if(head==null||head.next==null) return head;
//递归体
ListNode newHead = head.next;
head.next=swapPairs(newHead.next);
newHead.next=head;
//返回值
return newHead;
}
}
25. K 个一组翻转链表
很经典的题目了
148. 排序链表
本质就是递归归并,不断排序两个链表,其中可以参考21. 合并两个有序链表
class Solution {
public ListNode sortList(ListNode head) {
//边界条件
if(head==null||head.next==null)
return head;
//归并排序
//分割cut----找链表中点--快慢指针找
ListNode fast=head.next;
ListNode slow=head;
//快慢指针找中点
while(fast!=null&&fast.next!=null)
{
slow=slow.next;
fast=fast.next.next;
}
ListNode tmp = slow.next;
//断开链表
slow.next=null;
//递归,递归返回的过程就是归并的过程
ListNode left =sortList(head);
ListNode right =sortList(tmp);
ListNode ans_head = new ListNode(0);
ListNode cur =ans_head;
//排序链表
while(left!=null&&right!=null)
{
if(left.val<right.val)
{
cur.next=left;
left=left.next;
}
else
{
cur.next=right;
right=right.next;
}
cur=cur.next;
}
if(left!=null)
cur.next=left;
if(right!=null)
cur.next=right;
return ans_head.next;
}
}
23. 合并 K 个升序链表
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode ans = null;
for(ListNode list:lists)
ans = merge_two_Lists(ans,list);
return ans;
}
private ListNode merge_two_Lists(ListNode l1,ListNode l2)
{
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while(l1!=null&&l2!=null)
{
if(l1.val<l2.val)
{
cur.next=l1;
l1=l1.next;
}
else
{
cur.next=l2;
l2=l2.next;
}
cur=cur.next;
}
cur.next=(l1==null)?l2:l1;
return dummy.next;
}
}
146. LRU 缓存
class LRUCache {
//采取哈希链表 哈希表查找快,但是数据无固定顺序;链表有顺序之分,插入删除快,但是查找慢。
private final Map<Integer,Integer> cache =new LinkedHashMap<Integer,Integer>();
private final int capacity;
public LRUCache(int capacity) {
this.capacity=capacity;
}
//抽出来(删除一个节点)放最上面(链表添加一个节点)
public int get(int key) {
if(!cache.containsKey(key))
return -1;
//删除一个节点
int value = cache.remove(key);
//放在最上面,就是尾部
//只能从尾部插入,也就是说靠尾部的数据是最近使用的,靠头部的数据是最久为使用的。
cache.put(key,value);
return value;
}
//一摞书,放入一本新书,如果已经有,把它抽出来放最上面
public void put(int key, int value) {
if(cache.remove(key)!=null)
{
cache.put(key,value);
return;
}
if(cache.size()==capacity)
{
int old_key=cache.keySet().iterator().next();
cache.remove(old_key);//移除最久未使用key
}
cache.put(key,value);
}
}