hot100-链表相关

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);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值