马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
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 这个表达式可以确保新的索引处于 0 到 n - 1 的范围内,也就是在数组的有效索引区间内。
示例:
原数组长度为5,我们要将原数组中索引为2的元素往右边移动7位的时候等于是:(2+7)%5=4 = 7%5 =2.就是将原数组往右边移动2.
使用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 天的价格。
你只能选择 某一天 买入这只股票,并选择在 将来的某一个差别的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
题目解读:我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。别的,第二个数字(卖出价格)必须大于第一个数字(买入价格)。
情势上,对于每组 i 和 j(其中 j>i)我们需要找出 max(prices[j]−prices)。
方法一
暴力法
代码表现
- 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 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
思绪
在给定的股票价格数组中,天天都能决定是否买卖股票,且任何时候最多持有一股股票,还允许在同一天买卖。那么,只要后一天的股票价格比前一天高,就可以通过在前一天买入、后一天卖出的操作来获取利润。
我们要做的就是找出所有如许的价格上升区间,并将这些区间的利润累加起来,就能得到最大利润。
代码表现
- 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、跳跃游戏Ⅱ
需求:给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。
每个元素 nums 表现从索引 i 向后跳转的最大长度。换句话说,如果你在 nums 处,你可以跳转到任意 nums[i + j] 处:
返回到达 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 篇论文被引用的次数。计算并返回该研究者的 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 的长度。即为排序的空间复杂度。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |