力扣刷题总结

弗洛伊德算法

查找多源最短路径
首先将数据放入二维数组中int[][] dp
在这里插入图片描述
然后两重循环遍历数组
最外层循环判断将该节点加入路径后的最短距离

for(int k=1;k<=n;k++){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(dp[i][j]>dp[i][k]+dp[k][j]){
                dp[i][j]=dp[i][k]+dp[k][j];
            }
        }
    }
}

注意无穷大的取值:不能让dp[i][k]+dp[k][j]大于int类型所取最大值,会出错

迪杰斯特拉算法

适合查找单源最短路径
同弗洛伊德算法,有一个二维数组int[][] dp
有一个int[] dist数组,记录目标节点到各节点的最短距离
有一个int[] book数组,记录当前节点是否被标记

最外层循环,是每次循环标记一个节点
第一个循环是找到未标记的距离目标节点最近的节点,进行标记
第二个循环是找到未标记的所有节点,在经历标记节点后,进行距离更新

int u=0;
for(int k=1;k<=n;k++){
    u=-1;//记录下一个要标记的节点
    for(int i=1;i<=n;i++){
        if(!book[i]&&(u==-1||dist[i]>dist[u]){
            u=i;
        }
    }
    book[u]=true;//进行标记
    for(int i=1;i<=n;i++){
        if(!book[i]&&dist[i]>dist[u]+dp[u][i]){
            dist[i]=dist[u]+dp[u][i];
        }
    }
}

并查集

朋友圈
首先需要一个记父节点的数组,切记当fa[i]==i时也就是节点父节点为本身时,即为根节点
首先有一个找根节点的过程

public int find(int x){
if(x==fa[x]){
return x;
}
else {
return fa[x]=find(fa[x]);//路径压缩
}

然后是合并的过程
需要一个秩组rank[]

public void merge(int i,intj){
int x=find(i),y=find(j);
if(rank[x]<=rank[y]){
fa[x]=y;
}
else{fa[y]=x;}
if(rank[x]==rank[y]&&x!=y)rank[y]++;
}

贪心算法

  1. Assign Cookies (Easy)
    题目描述
    有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃
    最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩
    子可以吃饱。
    输入输出样例
    输入两个数组,分别代表孩子的饥饿度和饼干的大小。输出最多有多少孩子可以吃饱的数
    量。
    Input: [1,2], [1,2,3]
    Output: 2
    题解:找到最饥饿度的孩子所对应的最小的饼干。
public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g); //进行排序才能将最小满足的孩子与最小饼干匹配
		Arrays.sort(s);
		int i=0,j=0;
        while(i<g.length&&j<s.length){//注意在这个地方只需要在饼干满足的情况下,计数孩子
            if(s[j]>=g[i])i++;
            j++;
        }
        return i;
    }

链表

链表是最简单的线性的、动态数据结构。理解它是理解树结构、图结构的基础。
21.合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例1
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
题解:

class Solution{
        public ListNode mergeTwoLists(ListNode l1,ListNode l2){
         ListNode next=new ListNode(0);
         ListNode res=next;
         while(l1!=null&&l2!=null){
             if(l1.val<=l2.val){
                 next.next=new ListNode(l1.val);
                 l1=l1.next;
             }else{
                 next.next=new ListNode(l2.val);
                 l2=l2.next;
             }
             next=next.next;
         }
         if(l1!=null)next.next=l1;
         if(l2!=null)next.next=l2;
         return res.next;
        }
}

我自己的想法:利用归并排序,新建链表按顺序放置。

l1小
l2小
next
l1
l2
res

首先利用到了额外的空间,所以空间复杂度是O(n+m),时间复杂度是遍历两个链表所以也是O(n+m)
第一种方法:迭代
也就是我上面的这种方式,但是不是每一个结点都需要新建一个结点,只需要一个哨兵结点,记住链表的位置就行

class Solution{
        public ListNode mergeTwoLists(ListNode l1,ListNode l2){
         ListNode next=new ListNode(0);//哨兵结点
         ListNode res=next;
         while(l1!=null&&l2!=null){
             if(l1.val<=l2.val){
                 next.next=l1;
                 l1=l1.next;
             }else{
                 next.next=l2;
                 l2=l2.next;
             }
             next=next.next;
         }
         if(l1!=null)next.next=l1;
         if(l2!=null)next.next=l2;
         return res.next;
        }
}

此时的空间复杂度为O(1)
第二种方法:递归
每次递归就决定下一个添加到结果里的结点。例如 l1.val<l2.val,那么第一个节点就是l1,需要return l1,并决定下一个节点的值是下一次递归的结果。

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null)return l2;
        if(l2==null)return l1;
        if(l1.val<l2.val){
            l1.next=mergeTwoLists(l1.next,l2);
            return l1;
        }else{
            l2.next=mergeTwoLists(l2.next,l1);
            return l2;
        }
    }

因为递归调用mergeTwoLists函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时mergeTwoLists函数最多被调用n+m次,因此空间复杂度O (n+m),时间复杂度O (n+m)
141.环形链表
给定一个链表,判断链表中是否有环。
题解:
第一种方法:利用快慢指针

public boolean hasCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow)return true;
        }
        return false;
    }

时间复杂度O(N),N为链表中的节点数
空间复杂度O(1),只额外使用了两个指针
第二种方法:利用哈希表

public boolean hasCycle(ListNode head) {
       HashSet<ListNode> set=new HashSet<>();
       while(head!=null){
           if(!set.add(head)){
               return true;
           }
           head=head.next;
       }
       return false;
    }

时间复杂度O(N),空间复杂度O(N)
203.移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
第一种方法:迭代(利用哨兵节点)

public ListNode removeElements(ListNode head, int val) {
           ListNode prehead=new ListNode();
           ListNode pre=prehead;
           prehead.next=head;
           ListNode cur=head;
           while(cur!=null){
               if(cur.val==val){
                   pre.next=cur.next;
                   cur=pre.next;
               }else{
                   pre=cur;
                   cur=cur.next;
               }
           }
           return prehead.next;
    }

第二种方法:递归(注意返回的是删除元素后的链表头节点,所以只需要判断当前节点是否需要删除.

public ListNode removeElements(ListNode head, int val) {
        if(head==null)return null;
        head.next=removeElements(head.next,val);
        return head.val==val?head.next:head;
    }

空间复杂度O(N),时间复杂度O(N)
705.设计哈希集合

class MyHashSet {
    private static final int BASE = 769;
    private LinkedList[] data;

    /** Initialize your data structure here. */
    public MyHashSet() {
        data = new LinkedList[BASE];
        for (int i = 0; i < BASE; ++i) {
            data[i] = new LinkedList<Integer>();
        }
    }
    
    public void add(int key) {
        int h = hash(key);
        Iterator<Integer> iterator = data[h].iterator();
        while (iterator.hasNext()) {
            Integer element = iterator.next();
            if (element == key) {
                return;
            }
        }
        data[h].offerLast(key);
    }
    
    public void remove(int key) {
        int h = hash(key);
        Iterator<Integer> iterator = data[h].iterator();
        while (iterator.hasNext()) {
            Integer element = iterator.next();
            if (element == key) {
                data[h].remove(element);
                return;
            }
        }
    }
    
    /** Returns true if this set contains the specified element */
    public boolean contains(int key) {
        int h = hash(key);
        Iterator<Integer> iterator = data[h].iterator();
        while (iterator.hasNext()) {
            Integer element = iterator.next();
            if (element == key) {
                return true;
            }
        }
        return false;
    }

    private static int hash(int key) {
        return key % BASE;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值