力扣刷题小记7

博主个人博客网站:文客
这个系列主要记录在力扣刷题的总结和问题
如果你想每天和我一起刷题,可以关注一下我的个人博客网站:文客,我会每天在这里更新技术文章和面试题,也会及时收到大家的评论与留言,欢迎各位大佬来交流!

155. 最小栈

设计一个支持 pushpoptop 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

示例 1:

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

思路:

看题解有用链表来实现的,用链表也是一个很好的思路,但是均摊下来,复杂度并不低。我是直接使用Stack,然后维护一个最小值,每次插入元素时,都与最小值比较,如果有更小的元素插入进来,就更新最小值。当出栈的元素为最小值时,遍历栈,更新最小值,这里是O(n)的复杂度,但是从概率学的角度来想,又不是每次都会弹出最小的元素,所以我想也是可以接受的。

题解:

class MinStack {
    Stack<Integer> stack;
    Integer minVal;

    public MinStack() {
        stack = new Stack<>();
        minVal = Integer.MAX_VALUE;
    }
    
    public void push(int val) {
        stack.push(val);
        if(val < minVal){
            minVal = val;
        }
    }
    
    public void pop() {
        int popVal = stack.pop();
        if(popVal == minVal){
            minVal = Integer.MAX_VALUE;
            for(int num : stack){
                minVal = Math.min(minVal,num);
            }
        }
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return minVal;
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

160. 相交链表

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

图示两个链表在节点 c1 开始相交**:**

img

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
  • listA - 第一个链表
  • listB - 第二个链表
  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数

评测系统将根据这些输入创建链式数据结构,并将两个头节点 headAheadB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案

示例 1:

img

输入:intersectVal = 8, listA = [4,1,8,4,5],  listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

img

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [1,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

img

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

思路:

先计算两个链表的长度,然后把他们的起点对其,依次遍历,如果有相同节点,证明相交,直接返回相交节点,如果没有找到则返回null

题解:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int len1 = 0;
        int len2 = 0;
        ListNode p1 = headA;
        ListNode p2 = headB;
        while(p1 != null){
            len1++;
            p1 = p1.next;
        }
        while(p2 != null){
            len2++;
            p2 = p2.next;
        }
        p1 = (len1 > len2) ? headA : headB;
        p2 = (p1 == headA) ? headB : headA;
        for(int i = 0; i < Math.abs(len1 - len2); i++){
            p1 = p1.next;
        }
        while(p1 != null && p2 != null){
            if(p1 == p2){
                return p1;
            }
            p1 = p1.next;
            p2 = p2.next;
        }
        return null;
    }
}

169. 多数元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入:nums = [3,2,3]
输出:3

示例 2:

输入:nums = [2,2,1,1,1,2,2]
输出:2

思路:

多数元素,即是众数。最简单暴力的方式就是先排序,然后返回下标为nums.length / 2的数据。

效率最高的方式是摩尔计数法。维护一个计数器,当计数器为0时,将当前值赋予res,遇到相同元素计数器加一,遇到不同元素计数器减一。最后返回res,一定是出现次数最多的。

题解:

class Solution {
    public int majorityElement(int[] nums) {
        int res = 0;
        int count = 0;
        for(int i = 0; i < nums.length; i++){
            if(count == 0){
                res = nums[i];
                count++;
            } else if(res != nums[i]){
                count--;
            } else if(res == nums[i]){
                count++;
            }
        }
        return res;
    }
}

215. 数组中的第K个最大元素

给定整数数组 nums 和整数 k,请返回数组中第 **k** 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

思路:

使用优先级队列,队列的大小为k,堆顶就是第k大的元素。

题解:

class Solution {
    PriorityQueue<Integer> queue;
    public int findKthLargest(int[] nums, int k) {
        queue = new PriorityQueue<>(k);
        for(int num : nums){
            if(queue.size() < k){
                queue.offer(num);
            } else if(queue.peek() < num){
                queue.poll();
                queue.offer(num);
            }
        }
        return queue.peek();
    }
}

221. 最大正方形

在一个由 '0''1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。

示例 1:

img

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:4

示例 2:

img

输入:matrix = [["0","1"],["1","0"]]
输出:1

示例 3:

输入:matrix = [["0"]]
输出:0

思路:

使用dp,dp数组代表i,j位置内,最大正方形的边长

题解:

class Solution {
    public int maximalSquare(char[][] matrix) {
        int[][] dp = new int[matrix.length + 1][matrix[0].length + 1];
        int len = 0;
        for(int i = 1; i <= matrix.length; i++){
            for(int j = 1; j <= matrix[0].length; j++){
                if(matrix[i - 1][j - 1] == '1'){
                    dp[i][j] = 1 + Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j],dp[i][j - 1]));
                    len = Math.max(len,dp[i][j]);
                }
            }
        }
        return len * len;
    }
}

博客原文地址

力扣刷题小记7
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九天漩女

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值