【JAVA刷题初阶】刷爆力扣第六弹——数组

文章目录

  • 前言:关于JAVA刷题
    • 第一题:买卖股票的最佳时机
      • 题目描述
      • 示例
      • 提示
      • 题解
    • 第二题:多数元素
      • 题目描述
      • 示例
      • 提示
      • 题解
    • 第三题:删除有序数组中重复项
      • 题目描述
      • 示例
      • 提示
      • 题解


前言:关于JAVA刷题

关于JAVA的学习出了看视频以外,那就是刷题了,朋友们,你们有没有过这样的感觉,在网上看了视频过后感觉自己什么都听懂了,但就是写题和做项目时无从下手,或者就是因为某个细节一直错一直改,那背后的原因是什么呢?四个字——题刷少了,这里新一建议去Leetcode看看,那里的题库资源很丰富,并且在全球都有广泛涉猎。不仅如此,这里还有 课程 + 刷题 + 面经 + 求职 + 讨论区分享解题思路,用过的人都说好
在这里插入图片描述
除此之外,我的建议是初学者从简单题开始练习,因为简单题是一切题的基础,一切的困难题都是从简单题衍生而来的,每天刷那么2~3题,后期再慢慢刷中等题,困难题,经过一段时间后会有很不错的提升
在这里插入图片描述
此外,在我们有一定的提升之后,我们便可以去刷剑指offer了,在这里预祝各位大学生以及初学者都拿到自己满意的offer!


第一题:买卖股票的最佳时机


做题链接戳这里:121.买卖股票的最佳时机

题目描述

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例2

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

提示

● 1 <= prices.length <= 105
● 0 <= prices[i] <= 104

题解

常规思路:

我们看到这道题第一反应是什么?嵌套遍历数组求相减的最小值?我们试了试发现结果为超出时间限制。。。因为它的长度最大可以为10的5次方,故嵌套遍历会超出时间限制,那么我们怎么减少时间呢,将它的时间复杂度控制在O(n),我们知道要求最大利润:必须当前数字减最小值得到的值跟已记录的利润比较,较大的为最大利润,那么我们用两个变量来记录利润最大值和最小值即可,最后返回利润最大值即可

class Solution {
    public int maxProfit(int[] prices) {
        if (prices.length <= 1){
            return 0;
        }
        int min = prices[0];
        int max = 0;
        for (int i = 1; i < prices.length; i++) {
            max = Math.max(max, prices[i] - min);
            min = Math.min(min,prices[i]);
        }
        return max;
    }
}

【JAVA刷题初阶】刷爆力扣第六弹——数组_第1张图片

第二题:多数元素


做题链接戳这里,169.多数元素

题目描述

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

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

示例

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

示例2

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

提示

● n == nums.length
● 1 <= n <= 5 * 104
● -109 <= nums[i] <= 109

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

题解

这道题该怎么弄呢?需要找到出现大于等于n / 2次的数字,似乎遍历的话会很麻烦呢?没有思路,来来来,我给大家玩个故事:

玩一个诸侯争霸的游戏,假设你方人口超过总人口一半以上,并且能保证每个人口出去干仗都能一对一同归于尽。最后还有人活下来的国家就是胜利。

那就大混战呗,最差所有人都联合起来对付你(对应你每次选择作为计数器的数都是众数count),或者其他国家也会相互攻击(会选择其他数作为计数器的数),但是只要你们不要内斗,最后肯定你赢。

最后能剩下的必定是自己人。

所以只要存在大于等于一半的数字,最后互相对拼消耗,最后剩下来的必然是最多的数字

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

【JAVA刷题初阶】刷爆力扣第六弹——数组_第2张图片

第三题:删除有序数组中重复项


做题链接戳这里:26.删除有序数组中重复项

题目描述

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被 通过。

示例

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例2

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素

提示

● 1 <= nums.length <= 3 * 104
● -104 <= nums[i] <= 104
● nums 已按 升序 排列

题解

常规思路

首先,我们最容易想到的就是嵌套遍历数组,由于其实有序的,故所有重复数字排列在一起,我们遇到重复数字则嵌套遍历,直到紧挨的元素不相等,然后再移动数组元素,既可以达到删除的效果。

class Solution {
    public int removeDuplicates(int[] nums) {
        int size = nums.length;
        for (int i = 0; i < size - 1; i++) {
            if (nums[i] == nums[i + 1]){
                int j = i;
                while (j < size - 1 && nums[j] == nums[j + 1]){
                    j++;
                }
                int index = j - i;
                for (int k = j; k < size; k++) {
                    nums[k - index] = nums[k];
                }
                size -= index;
            }
        }
        return size;
    }
}

【JAVA刷题初阶】刷爆力扣第六弹——数组_第3张图片

优解

虽然通过了所有用例,但这时间复杂度感人,我们能不能只遍历一次数组达到删除的效果呢?我们看到返回的实际是数组长度,然后再根据这个长度去判断你的数组是否合理,那么我们借一步说话:是不是每次遇到重复元素时继续遍历数组,一旦不重复了,我们是不是可以直接把那个非重复元素,直接放在其重复初始位置,反正最后它只检查你返回的数组大小,如此往复最后返回索引即可

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums == null || nums.length == 1){
            return nums.length;
        }
        int i = 0;
        int j = 1;
        while (j < nums.length){
            if (nums[i] == nums[j]) {
                j++;
            }else{
                i++;
                nums[i] = nums[j];
                j++;
            }
        }
        return i + 1;//返回其长度
    }
}

【JAVA刷题初阶】刷爆力扣第六弹——数组_第4张图片

你可能感兴趣的:(JAVA刷爆力扣训练营,leetcode,java,算法)