补天计划-----第0天---leetcode刷题笔记

第一题—两个数组的交集||

在这里插入图片描述

方法一:

用HashMap统计元素个数,然后对比个数大小,选择小的放入新数组

    /*
    方法一:较差的一种方法,时间复杂度为O(m+n);
     */
    public static int[] intersect(int[] nums1, int[] nums2) {
        Map<Integer, Integer> map1 = new HashMap<>();
        //统计nums1的数据
        for (int num : nums1) {
            //如果存在值就+1
            if (map1.containsKey(num)) {
                map1.replace(num, map1.get(num) + 1);
            } else {
                map1.put(num, 1);
            }
        }
        int[] fin = new int[Math.min(nums1.length, nums2.length)];//长度为短数组长度
        int i = 0;
        //统计nums2的数据
        for (int num : nums2) {
            if (map1.containsKey(num) && map1.get(num) != 0) {
                fin[i++] = num;
                map1.replace(num, map1.get(num) - 1);
            }
        }
        return Arrays.copyOfRange(fin, 0, i);
    }

方法二:


1.先使用快速排序算法进行排序,然后使用双指针进行遍历。

时间复杂度为O(nlogn),空间复杂度:O(min(m,n))

public static int[] intersect(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            return intersect(nums2, nums1);//将nums1作为数组较短的那一个
        }
        Arrays.sort(nums1);//排序
        Arrays.sort(nums2);
        int p = 0, d = 0, index = 0;//P:nums1的指针,d:nums的指针,index:result的下标
        int[] result = new int[nums1.length];
        while (p < nums1.length && d < nums2.length) {
            if (nums1[p] == nums2[d]) {//如果当前两个数相等就放进result中,指针后移
                result[index++] = nums1[p];
                d++;
                p++;
            } else if (nums1[p] > nums2[d]) {
                //如果p指向的数大于d指向的数,则让d向后移动
                d++;
            } else if (nums1[p] < nums2[d]) {
                //如果p指向的数小于d指向的数,则让p向后移动
                p++;
            }

        }
        return Arrays.copyOfRange(result, 0, index);
    }

进阶问题

  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
    ​ 如果已经排好序传入参数,则删去排序代码,采用双指针,时间复杂度降低为O(n)
  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
    采用Hash计数,时空间复杂度会低一些。

如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
自我理解:
内存是有限的,无法有效的对较长数组进行排序,采用方法一(hash计数)更合适,方法一只需要在map中读取一部分数据,符合题目要求。

LeetCode网友观点:
1.内存十分小,不足以将数组全部载入内存
2.哈希表十分耗费空间
3.选用空间复杂度最小的算法,即方法二。 解法:
1.改造方法二
2.常见排序算是都是用于数组内部属于内部排序,如果涉及磁盘属于外部排序
3.归并排序是天然适合外部排序的算法,可以将分割后的子数组写到单个文件中,归并时将小文件合并为更大的文件。
4.当两个数组均排序完成生成两个大文件后,即可使用双指针遍历两个文件,如此可以使空间复杂度最低。
代码为:

  public static int[] intersect(int[] nums1, int[] nums2) {
>     if (nums1.length > nums2.length) {
>         return intersect(nums2, nums1);//将nums1作为数组较短的那一个
>     }
>     sort(nums1);//归并排序,在下方
>     sort(nums2);
>     int p = 0, d = 0, index = 0;//P:nums1的指针,d:nums的指针,index:result的下标
>     int[] result = new int[nums1.length];
>     while (p < nums1.length && d < nums2.length) {
>         if (nums1[p] == nums2[d]) {//如果当前两个数相等就放进result中,指针后移
>             result[index++] = nums1[p];
>             d++;
>             p++;
>         } else if (nums1[p] > nums2[d]) {
>             //如果p指向的数大于d指向的数,则让d向后移动
>             d++;
>         } else if (nums1[p] < nums2[d]) {
>             //如果p指向的数小于d指向的数,则让p向后移动
>             p++;
>         }
> 
>     }
>     return Arrays.copyOfRange(result, 0, index); }

归并排序

归并排序算法转载于:https://www.cnblogs.com/chengxiao/p/6194356.html

img

img

public static void sort(int[] arr) {
    int[] temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
    sort(arr, 0, arr.length - 1, temp);
}

private static void sort(int[] arr, int left, int right, int[] temp) {
    if (left < right) {
        int mid = (left + right) / 2; //寻找中位值
        sort(arr, left, mid, temp); //对数组左边进行归并排序
        sort(arr, mid + 1, right, temp);//对数组右部进行归并排序
        merge(arr, left, mid, right, temp);//将两个有序的子数组合并

    }
}

private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
    int i = left;//左序列起始指针
    int j = mid + 1;//右序列起始指针
    int t = 0;//临时数组temp的指针
    while (i <= mid && j <= right) {
        if (arr[i] <= arr[j]) {
            temp[t++] = arr[i++];
        } else {
            temp[t++] = arr[j++];
        }
    }
    while (i <= mid) {//将左边剩余元素填充进temp
        temp[t++] = arr[i++];
    }
    while (j <= right) {//将右序列剩余元素填充进temp中
        temp[t++] = arr[j++];
    }
    t = 0;
    //将temp中的元素全部拷贝到原数组中
    while (left <= right) {
        arr[left++] = temp[t++];
    }
}
买卖股票的最佳时机

在这里插入图片描述

假定每一天都是最低价格,寻找到历史最低价格min,在min后面的每一天都判定一下当日价格是否低于min,不是的话就计算利润最大值并前面的利润最大作比较。

时间复杂度是O(1)

public static int maxProfit(int[] prices) {
        int max = 0;
        int min = Integer.MAX_VALUE;
        for (int price : prices) {
            if (price < min) {
                min = price;//寻找历史最低点
            } else if (price - min > max) {
                max = price - min;//在可卖出的天数中,比较收益,选择最大的那一个。
            }
        }
        return max;
    }
           min = price;//寻找历史最低点
        } else if (price - min > max) {
            max = price - min;//在可卖出的天数中,比较收益,选择最大的那一个。
        }
    }
    return max;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

长雨已停

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

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

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

打赏作者

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

抵扣说明:

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

余额充值