LeetCode TOP100 热题(2)

    如果你时间比较紧迫,为了找工作而刷题,我建议你先刷热门推荐,一共100道题。

先刷热题 HOT 100,再刷精选 TOP 面试题,之后刷其他的题。

    接下来的一段时间,我会把做的这些题做一个总结,每天在 每日一题算法群中公布题目和解法,定时推送公众号,欢迎各位关注公众号加入群聊,大家一起监督一起努力。

LeetCode 3 无重复字符的最长子串

  给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

分析

1.暴力法

   逐个检查所有的子字符串,看它是否不含有重复的字符。暴力法非常简单,但它太慢了。那么我们该如何优化它呢?

    在暴力法中,我们会反复检查一个子字符串是否含有有重复的字符,但这是没有必要的。如果从索引 i 到 j - 1 之间的子字符串 sij已经被检查为没有重复字符。我们只需要检查 s[j]对应的字符是否已经存在于子字符串 sij中。

    要检查一个字符是否已经在子字符串中,我们可以检查整个子字符串,这将产生一个复杂度为 O(n^2)

    通过使用 HashSet 作为滑动窗口,我们可以用 O(1)的时间来完成对字符是否在当前的子字符串中的检查。

2.(利用哈希表)

    事实证明,我们可以一次完成。在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。如果它存在,那我们已经找到了对应解,并立即将其返回。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map=new HashMap();
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(target-nums[i]))//找到结果 直接返回
                return new int[]{map.get(target-nums[i]),i};
            else//找不到结果 将当前值存入哈希
                map.put(nums[i],i);
        }
        return new int[]{-1,-1};
    }
}

滑动查看更多图片

LeetCode 4 寻找两个有序数组的中位数

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

    请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

    你可以假设 nums1 和 nums2 不会同时为空。

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0
nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

分析

1.暴力

    简单粗暴,先将两个数组合并,两个有序数组的合并也是归并排序中的一部分。然后根据奇数,还是偶数,返回中位数。

2.其实,我们不需要将两个数组真的合并,我们只需要找到中位数在哪里就可以了。

    用 len 表示合并后数组的长度,如果是奇数,我们需要知道第 (len+1)/2 个数就可以了,如果遍历的话需要遍历 int(len/2 ) + 1 次。如果是偶数,我们需要知道第 len/2和 len/2+1 个数,也是需要遍历 len/2+1 次。所以遍历的话,奇数和偶数都是 len/2+1 次。

    返回中位数的话,奇数需要最后一次遍历的结果就可以了,偶数需要最后一次和上一次遍历的结果。所以我们用两个变量 left 和 right,right 保存当前循环的结果,在每次循环前将 right 的值赋给 left。这样在最后一次循环的时候,left 将得到 right 的值,也就是上一次循环的结果,接下来 right 更新为最后一次的结果。

public double findMedianSortedArrays(int[] A, int[] B) {
    int m = A.length;
    int n = B.length;
    int len = m + n;
    int left = -1, right = -1;
    int aStart = 0, bStart = 0;
    for (int i = 0; i <= len / 2; i++) {
        left = right;
        if (aStart < m && (bStart >= n || A[aStart] < B[bStart])) {
            right = A[aStart++];
        } else {
            right = B[bStart++];
        }
    }
    if ((len & 1) == 0)
        return (left + right) / 2.0;
    else
        return right;
}

3.利用两个堆 一个大根堆 一个小根堆 大根堆存储两个数组中小于中位数的数 小根堆存储两个数组中大于等于中位数的数
    用 len 表示合并后数组的长度,如果是奇数,直接取小根堆的堆顶。如果是偶数,我们需要知道第 len/2和 len/2+1 个数,也是需要知道大根堆和小根堆的堆顶即可

class Solution {
    private PriorityQueue<Integer> up=new PriorityQueue<>();
    private PriorityQueue<Integer> down=new PriorityQueue<>(new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2-o1;
        }
    });
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        for (int i = 0; i <nums1.length ; i++) {
            insert(up,down,nums1[i]);
        }
        for (int i = 0; i < nums2.length; i++) {
            insert(up,down,nums2[i]);
        }
        if((nums1.length+nums2.length)%2 == 1)
            return up.element();
        else
            return ((up.element()+down.element())/2.0);
    }


    public static void insert(PriorityQueue<Integer> up,PriorityQueue<Integer> down,int num) {
        if((down.size()==0) || num>=up.element())
            up.add(num);
        else{
            down.add(num);
            up.add(down.poll());
        }
        if(up.size()-down.size()>1)
            down.add(up.poll());

    }
}

快来加入 每日一题算法群 吧

    下期预告:

                            5. 最长回文子串

                           

                                    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值