数据结构与算法(LeetCode刷题记录及相应知识点整理,含题解及顺序 Java版)//..

数据结构与算法(LeetCode刷题记录及相应知识点整理,含题解及顺序 Java版)

一. 链表

1) 21.合并两个有序链表 (简单) 2021.10.9

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    
    
        ListNode dummy = new ListNode(-1), p = dummy;
        ListNode p1 = l1, p2 = l2;
     
        // -1 也可写成 0/1 其他数
        // 区分 == 和 =
        // 根据测验 最后return的 不能是p.next 需要是dummy.next才可以 区别在于p在代码体中出现了. dummy没 (还待考证)

        while(p1 != null && p2 != null) {
    
    
            if(p1.val < p2.val) {
    
    
                p.next = p1;
                p1 = p1.next;
            }else {
    
    
                p.next = p2;
                p2 = p2.next;
            }
            p = p.next;
        }
        if(p1 != null) {
    
    
            p.next = p1;
        }
        if(p2 != null) {
    
    
            p.next = p2;
        }
        return dummy.next;
    }
}

技巧1: 虚节点

2) 23. 合并K个升序链表 (困难) 2021.10.13

第一次:
弄了很久, 但还是存在一些问题
要再多仔细弄弄 把细节弄清楚
小黄鸭法
心得:
不会的知识 一点一点查 耐心坚持总会做出来的

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    
    public ListNode mergeKLists(ListNode[] lists) {
    
    
   		
   	解法一: 优先队列
   		
        if(lists.length == 0) {
    
    
            return null;
        }

        ListNode dummy = new ListNode(-1);
        ListNode p = dummy;
        PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);
        
        /*
        PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>() {
            @Override
            public int compare(ListNode a, ListNode b) {
                return a.val - b.val;
            }
        });
        */

        for(ListNode head : lists) {
    
    
            if (head != null) {
    
    
                pq.add(head);
            }
        }

        while(!pq.isEmpty()) {
    
    
            ListNode node = pq.poll();
            p.next = node;
            if(node.next != null) {
    
    
                pq.add(node.next);
            }
            p = p.next;
        }
            
        return dummy.next;

        /*
        if (lists.length == 0) {
            return null;
        }
        
        // 虚拟头结点
        ListNode dummy = new ListNode(-1);
        ListNode p = dummy;
        // 优先级队列,最小堆
        PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b)-> a.val - b.val);
        // 将 k 个链表的头结点加入最小堆
        for (ListNode head : lists) {
            if (head != null)
                pq.add(head);
        }

        while (!pq.isEmpty()) {
            // 获取最小节点,接到结果链表中
            ListNode node = pq.poll();
            p.next = node;
            if (node.next != null) {
                pq.add(node.next);
            }
            // p 指针不断前进
            p = p.next;
        }
        return dummy.next;
        */

   	解法二: 


    }
}

优先队列pq中的元素个数最多是k,所以一次poll或者add方法的时间复杂度是 O(logk),所有链表节点都会被加入和弹出pq,所以算法的整体时间复杂度是:
时间复杂度为 O(Nlogk)
N:链表的节点总数
k:链表条数

相关知识点补充

一. 链表

1) 链表和数组的区别及优缺点

​ 区别:
​ (1)内存:数组静态分布内存,链表动态分布内存;
​ 数组在内存中是连续的,链表不连续;
​ (2)复杂度:
​ ①查找时:
​ 数组利用索引定位,查找的时间复杂度是O(1),
​ 链表通过遍历定位元素,查找的时间复杂度是O(n);
​ ② 插入和删除:
​ 数组插入和删除要移动其他元素, 时间复杂度是O(n),
​ 链表的插入和删除不需要移动其他元素, 时间复杂度是O(1);

​ 数组的优缺点:
​ (1)优点:
​ 复杂度: 随机访问性比较强,可以通过下标进行快速定位。查找速度快
​ (2)缺点:
​ 内存: ①会造成内存的浪费. 因为内存是连续的,所以在创建数组的时候必须规定其大小,如果不合适,就会造成内存的浪费。
​ ②内存空间要求高. 创建一个数组,必须要有足够的连续内存空间。
​ ③数组的大小是固定的,在创建数组的时候就已经规定好,不能动态拓展, 如果要扩容, 需要重新分配一块更大的空间, 再把所有数据全部复制过去.
​ 复杂度: ④插入和删除的效率低,需要移动其他元素。

​ 链表的优缺点:
​ (1)优点:
​ 内存: ①内存利用率高,不会浪费内存,可以使用内存中细小的不连续的空间,只有在需要的时候才去创建空间。大小不固定,拓展很灵活。
​ 复杂度: ②插入和删除的效率高,只需要改变指针的指向就可以进行插入和删除。
​ (2)缺点:
​ 内存: ①由于每个元素必须存储指向前后元素位置的指针, 会消耗相对更多的存储空间.
​ 复杂度: ②查找的效率低,因为链表是从第一个节点向后遍历查找。

​ 适用场景:
​ 数组: 数据量固定, 频繁查找, 较少删改
​ 链表: 数据量不固定, 频繁增删, 较少查询

2) 优先队列

①Java中重写优先队列比较器2021.10.21

//匿名内部类
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){
    
    
    @Override
    public int compare(Integer o1, Integer o2){
    
    
        //如果认为o1优先级比o2高,先出o1 compare返回<0的整数
        //如果认为o2优先级比o1高,先出o2 compare返回>0的整数
        //如果一样,返回0
        return o2-o1;
    }
});

/*
原理就是
结果为-,返回前面的一个元素o1
结果为+,返回后面的一个元素o2

上面是将小根堆换成了大根堆,小根堆就是return o1-o2
*/


待看

fucking-algorithm/刷题技巧.md at master · labuladong/fucking-algorithm · GitHub

持续更新

おすすめ

転載: blog.csdn.net/weixin_46644403/article/details/120669443