每日一练(day12&PriorityQueue)

Posted 'or 1 or 不正经の泡泡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一练(day12&PriorityQueue)相关的知识,希望对你有一定的参考价值。

文章目录

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

本博文优先在掘金社区发布!

题目

每日一练由原来的>=5道题目改>=三道题目,没办法,>=五道题有点多。

第一道先来个简单的

删除链表中的节点

输入: head = [4,5,1,9], node = 5 输出: [4,1,9] 解释: 指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9

这个就没啥好说了,嘻嘻~


class Solution 
    public void deleteNode(ListNode node) 
        node.val = node.next.val;
        node.next = node.next.next;
    

回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

正常解法

这个其实和我们以前做的题目都是一样的。
但是咧现在是在咱们的这个链表里面实现,当然代码也简单。
最简单最直接的思路就是拿到里面的值,然后给一个数组里面然后去判断。

class Solution 
    public boolean isPalindrome(ListNode head) 
        List<Integer> temp = new ArrayList<Integer>();

        // 将链表的值复制到数组中
        ListNode currentNode = head;
        while (currentNode != null) 
            temp.add(currentNode.val);
            currentNode = currentNode.next;
        

        // 使用双指针判断是否回文
        int front = 0;
        int back = temp.size() - 1;
        while (front < back) 
            if (!temp.get(front).equals(temp.get(back))) 
                return false;
            
            front++;
            back--;
        
        return true;
    

当然这个显然不是最“优解”,最好的办法其实我们还是可以用到这个栈的。判断回文核心就是判断前面等不等于后面嘛,如果使用栈,那么按顺序存进去,然后再一个一个出栈对比,其实就是相当于反转字符串。但是这样意味着扫描了两遍,第一遍入栈,第二遍对比,但是前面的方式由于是双指针,所以可以对半,第二遍不用那么麻烦。但是这个方法太“简单”不符合我们的身份!所以我们要用到这个栈,没错我又来了负优化了~我们使用递归!

递归


class Solution 
    private ListNode front;

    private boolean recursivelyCheck(ListNode currentNode) 
        if (currentNode != null) 
            if (!recursivelyCheck(currentNode.next)) 
                return false;
            
            if (currentNode.val != front.val) 
                return false;
            
            front = front.next;
        
        return true;
    

    public boolean isPalindrome(ListNode head) 
        
        front = head;
        return recursivelyCheck(head);
    

叫我优化戴师:

		执行耗时:18 ms,击败了5.45% 的Java用户
		内存消耗:55.6 MB,击败了7.19% 的Java用户

数据流的中位数

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

  • void addNum(int num) - 从数据流中添加一个整数到数据结构中。
  • double findMedian() - 返回目前所有元素的中位数。

名字很呼哨,其实说的东西很简单,所谓中位数不就是有这样一个数,一个数组,一半比它小,一半比他大嘛,同时注意元素奇偶即可。之后是注意到我们这个是数据流,数据流!你要想拿到中位数,你必须保证,你的序列是有序的,这样我就可以保证在O(1)的复杂度拿到中位数。

所以这个题目的问题在于我如何保证,能够让用户输入的数据是一个有序的状态!
如果是加一个数据,我就让它排序一次用Arrary.sort()的话显然这做的话,如果数据量极大,那就是作死行为。而且我们是一个数据流,我们数据的长度可能会随时改变,所以我们必须在让这个数据进来的时候就是有序的。

所以在这里我们很自然地就想到了大小堆。

这不就有序了嘛。那问题了来了如何实现我们的代码,这个时候就要体现我们高级语言的好处了(说句实话让我手写一个我也不行)

我们使用java 里面的 PriorityQueue

PriorityQueue 队列

这个哥们是基于二叉树默小堆
(要注意:默认的PriorityQueue并非保证了整个队列都是有序的,只是保证了队头是最小的)

那么如果我们要实现大根堆的话我们可以这样。

PriorityQueue <Integer> A;
A=new PriorityQueue<>(new Comparator<Integer>() 

			@Override
			public int compare(Integer o1, Integer o2) 
				// if(o2>o1)
                                //      return 1;
                                // else
                                //     if(o1==o2)
                                //          return 0;
                                //     else
                                //         return -1;
				return o2-o1;
			
);

这里的话我们直接使用lambda

maxHeap = new PriorityQueue<>((a, b) -> b - a);
class MedianFinder 

    PriorityQueue<Integer> maxHeap;

    PriorityQueue<Integer> minHeap;
    public MedianFinder() 

        maxHeap = new PriorityQueue<>((a, b) -> b - a);
        minHeap = new PriorityQueue<>();
    

    public void addNum(int num) 
        //先比较两个堆顶元素,保证大的数字在小堆,小的在大堆
        if (maxHeap.size() == minHeap.size() + 1) 
            maxHeap.offer(num);
            minHeap.offer(maxHeap.poll());
           
         else 
            minHeap.offer(num);
            maxHeap.offer(minHeap.poll());
        
    

    // 当数据流的元素数量为奇数时,中位数即为大顶堆maxHeap的堆顶元素。
    // 当数据流的元素数量为偶数时,中位数为大顶堆maxHeap和小顶堆minHeap堆顶元素的平均数。
    public double findMedian() 
        if (maxHeap.size() > minHeap.size()) 
            return maxHeap.peek();
         else 
            return (maxHeap.peek() + minHeap.peek()) / 2.0;
        
    

以上是关于每日一练(day12&PriorityQueue)的主要内容,如果未能解决你的问题,请参考以下文章

每日一练(day01)

每日一练(day02 手撕 KMP)

每日一练(day09补08,03,04)

每日一练(day05)

每日一练(day04)

每日一练(day03--动态规划dp)