当前位置: 首页 > news >正文

LeetCode面试热题150中6-11题学习笔记(用Java语言描述)

Day 02

6、轮转数组

需求:给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

方法一

核心思想

使用额外的数组来将每个元素放至正确的位置。用 n 表示数组的长度,遍历原数组,将原数组下标为 i 的元素放至新数组下标为 (i+k)modn 的位置,最后将新数组拷贝至原数组即可。

代码表示
public class Q6_1 {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] newArr = new int[n];  //创建新数组,长度等于原数组的长度
		k = k % n;	//处理K大于数组长度的情况
        
        for (int i = 0; i < n; ++i) {   //循环元素旋转
            newArr[(i + k) % n] = nums[i];
        }

        System.arraycopy(newArr, 0, nums, 0, n);    //复制回原数组newArr中
    }
}

代码详解

  • 第6-8行循环:

    • i:这是循环变量,代表原数组 nums 当前元素的索引。在循环里,i 会从 0 递增到 n - 1,从而遍历原数组的每一个元素。

    • k:它表示要将数组元素向右旋转的位数。比如,若 k = 3,就意味着每个元素要向右移动 3 个位置。

    • n:代表数组 nums 的长度。

在数组元素向右旋转的过程中,可能会出现元素移动到数组末尾后超出数组范围的情况。

(i + k) % n 这个表达式可以确保新的索引处于 0n - 1 的范围内,也就是在数组的有效索引区间内。

示例:

原数组长度为5,我们要将原数组中索引为2的元素往右边移动7位的时候等于是:(2+7)%5=4 = 7%5 =2.就是将原数组往右边移动2.

  • 第10行代码:

使用System.arraycopy方法将新数组newArr中的元素复制回原数组nums

arraycopy方法的参数依次为:源数组(newArr)、源数组的起始位置(0)、目标数组(nums)、目标数组的起始位置(0)以及要复制的元素数量(n)。

复杂度分析

时间复杂度: O ( n ) O(n) O(n),其中n是数组的长度。

空间复杂度: O ( n ) O(n) O(n).


7、买卖股票的最佳时机

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

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

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

题目解读:我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。此外,第二个数字(卖出价格)必须大于第一个数字(买入价格)。

形式上,对于每组 i 和 j(其中 j>i)我们需要找出 max(prices[j]−prices[i])。

方法一

暴力法

代码表示
public class Q7_1 {
    public int maxProfit(int[] prices) {
        int maxProfit = 0;  //初始化最大利润为0

        for (int i = 0; i < prices.length - 1; i++) {   //外层循环确认买入的时机

            for (int j = i + 1; j < prices.length; j++) {   //内存循环确认卖出的时机从i+1开始
                int profit = prices[j] - prices[i]; //当前卖出的利润

                if (profit > maxProfit) {   //如果当前利润大于最大例如,则更新maxprofit
                    maxProfit = profit;
                }
            }

        }
        return maxProfit;
    }
}
复杂度分析

时间复杂度: O ( n 2 ) O(n^2) O(n2),其中n是数组的长度。采用的双重循环进行遍历。

空间复杂度: O ( 1 ) O(1) O(1),只使用了常数级的额外空间。

缺点

时间复杂度较高,处理大规模数据导致性能问题。想办法将时间复杂度降到 O ( n ) O(n) O(n).

方法二

遍历一次数组

代码表示
public class Q7_2 {
    public int maxProfit(int[] prices) {
        int minPrice = Integer.MAX_VALUE;
        //初始化最低股票价格,初始化为的整形最大值,
        //这样在首次比较时,任何实际价格都会小于初始化的值从而被更新。
        int maxProfit = 0;

        for (int price : prices) {  //循环遍历
            //增强型for循环遍历prices数组,每次迭代price代表当前遍历到的价格
            if (price < minPrice) {
                minPrice = price;   //更新最低价格
            } else if (price - minPrice > maxProfit) {
                maxProfit = price - minPrice;   //计算更新当前的利润
            }
        }

        return maxProfit;
    }
}
复杂度分析

时间复杂度: O ( n ) O(n) O(n),只需要遍历一次数组。

空间复杂度: O ( 1 ) O(1) O(1),只使用了常数个变量。


8、买卖股票的最佳时机Ⅱ

需求:给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润

思路

在给定的股票价格数组中,每天都能决定是否买卖股票,且任何时刻最多持有一股股票,还允许在同一天买卖。那么,只要后一天的股票价格比前一天高,就可以通过在前一天买入、后一天卖出的操作来获取利润。

我们要做的就是找出所有这样的价格上升区间,并将这些区间的利润累加起来,就能得到最大利润。

代码表示
public class Q8_1 {
    public int maxProfit(int[] prices) {
        int profit = 0;

        //从第一天开始循环遍历
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] > prices[i - 1]) {    //如果后一天的价格比前一天高
                profit += prices[i] - prices[i - 1];    //累加利润
            }
        }
        return profit;
    }
}
复杂度分析

时间复杂度: O ( n ) O(n) O(n), n 是数组 prices 的长度。只进行一次遍历。

空间复杂度: O ( 1 ) O(1) O(1).


9、跳跃游戏

需求:给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false

方法一

思路

使用贪心算法来解决。贪心算法的核心思想是在每一步都尽可能地选择能跳到最远位置的方案。

代码表示
public class Q9_1 {
    public boolean CanJump(int[] nums) {
        int maxReach = 0;//记录从数组起始位置开始,当前能够到达的最远下标位置。

        //使用 for 循环遍历数组 nums,从数组的第一个下标(索引为 0)开始,直到数组的最后一个下标。
        for (int i = 0; i < nums.length; i++) {

            if (i > maxReach) {
                return false;
            }

            maxReach = Math.max(maxReach, i + nums[i]);
            /*i + nums[i] 表示从当前位置 i 出发,根据该位置上的数字 nums[i] 所能跳跃到的最远下标位置。
            使用 Math.max 函数比较 maxReach 和 i + nums[i] 的大小,
            将较大值赋给 maxReach,以此更新当前能够到达的最远下标位置。*/

            if (maxReach >= nums.length - 1) {
                return true;
            }
            /*检查当前更新后的 maxReach 是否大于或等于数组的最后一个下标 nums.length - 1。
            如果满足条件,说明已经能够到达或超过数组的最后一个下标,直接返回 true。*/
        }
        return false;
    }
}
复杂度分析

时间复杂度: O ( n ) O(n) O(n), n 是数组的长度。只进行一次遍历。

空间复杂度: O ( 1 ) O(1) O(1).


10、跳跃游戏Ⅱ

需求:给定一个长度为 n0 索引整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i]
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]

思路

采用贪心算法,每次都尽可能的跳的远,以此来减少跳跃的总次数。

代码表示
public class Q10_1 {
    public int jump(int[] nums) {
        int n = nums.length;
        int jumps = 0;//记录跳跃的总次数
        int currentEnd = 0;//表示当前这一次跳跃所能到达的最远位置的边界,初始值为 0,意味着刚开始还未进行跳跃。
        int farthest = 0;//记录从当前位置以及之前的位置出发,所能到达的最远位置,初始值为 0。


        for (int i = 0; i < n - 1; i++) {
            farthest = Math.max(farthest, i + nums[i]);
            /*i + nums[i] 表示从当前位置 i 出发,根据该位置上的数字 nums[i] 所能跳跃到的最远位置。
            使用 Math.max 函数比较 farthest 和 i + nums[i] 的大小,
            将较大值赋给 farthest,以此更新从当前位置以及之前的位置出发所能到达的最远位置。*/

            if (i == currentEnd) {  //已经到达了当前这一次跳跃所能到达的最远位置的边界。
                jumps++;    //进行一次新的跳跃,所以将跳跃次数 jumps 加 1。
                currentEnd = farthest;  //表示新的一次跳跃所能到达的最远位置的边界。
            }
        }
        return jumps;

    }
}
复杂度分析

时间复杂度: O ( n ) O(n) O(n), n 是数组的长度。只进行一次遍历。

空间复杂度: O ( 1 ) O(1) O(1).


11、H指数

需求:给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数

根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。

方法一

排序法

整体思路

先将引用次数数组按降序排列,然后从大到小遍历排序后的数组,找出满足条件的最大 h 值。

代码表示
import java.util.Arrays;

class Q11_1 {
    public int hIndex(int[] citations) {

        Arrays.sort(citations);
        /*运用 Arrays.sort() 方法对 citations 数组进行升序排序。
        排序后,数组中的元素按引用次数从小到大排列。*/

        int h = 0, i = citations.length - 1;

        while (i >= 0 && citations[i] > h) {
            h++;
            i--;
        }
        /*i >= 0 确保索引 i 在数组的有效范围内。
        citations[i] > h 表示当前论文的引用次数大于当前的 h 指数,意味着可以继续增加 h 指数。*/

        return h;
    }
}
复杂度分析

时间复杂度:O(nlogn),其中 n 为数组 citations 的长度。即为排序的时间复杂度。

空间复杂度:O(logn),其中 n 为数组 citations 的长度。即为排序的空间复杂度。

相关文章:

  • 通过 spring ai 对接 deepseek ai 大模型通过向量数据库,完成 AI 写标书及构建知识库功能的设计与开发
  • 简约美观的地址发布页PHP源码带后台
  • 【3】k8s集群管理系列--包应用管理器helm之chart资源打包并推送到harbor镜像仓库
  • 粉末冶金齿轮学习笔记分享
  • Honor of Kings (S39) 13-win streak
  • Python中NumPy的随机操作
  • 5.1 GitHub订阅监控系统实战:FastAPI+SQLAlchemy高效架构设计与核心源码揭秘
  • 从一到无穷大 #45:InfluxDB MCP Server 构建:从工程实践到价值重构
  • 探秘 Python 网络编程:构建简单聊天服务器
  • RFID技术概览
  • 深入理解linux操作系统---第3讲 基本操作与基本管理
  • GD32的中断、定时器与PWM综合使用
  • FEA 仿真助力高速连接器设计中的信号完整性
  • 碰一碰发视频源码搭建技术开发,私有化部署,定制化开发
  • 【OpenCV】【XTerminal】talk程序运用和linux进程之间通信程序编写,opencv图像库编程联系
  • 数智读书笔记系列028 《奇点更近》
  • 批量给文件夹编排序号,支持数字序号及时间日期序号编排文件夹
  • 数组对象[object],五种如何去重方法 js
  • 【从零实现高并发内存池】- 项目介绍、原理 及 内存池详解
  • 小八股-CDN
  • 猎聘做简历的网站收费靠谱吗/seo前景
  • 免费 网站源码/免费二级域名注册申请
  • 朔城网站制作/sem推广托管公司
  • 上海专业网站建设报价/天津seo公司
  • 美橙做过网站案例/会计培训班需要学多长时间
  • 禅城网站建设公司/网络推广服务