LeetCode数组算法题(Java版)
Posted 3 ERROR(s)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode数组算法题(Java版)相关的知识,希望对你有一定的参考价值。
文章目录
一、删除有序数组中的重复项(26题)
原题如下:
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。
不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,0,0,0,0,1,1,1,2,2,3,3,3,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。
不需要考虑数组中超出新长度后面的元素。
1.双指针解法
如果数组长度为0则返回0;
定义一个快指针和一个慢指针,因为只要数组长度大于等于1了,他就至少返回一个不一样的数字。
所以我们从1号元素开始检索。我们的慢指针指向下一个元素要填入的位置,快指针从1开始遍历到第nums.length-1个元素,当nums[fast]!=nums[fast-1])的时候,说明num[fast]是一个没出现过的新数字(数组有序)我们就把快指针指向的数字赋值给慢指针,同时慢指针++,最终我们返回慢指针就ok了
num[0]-num[slow-1]就是我们要的答案。
参考代码:
class Solution
public int removeDuplicates(int[] nums)
if(nums.length==0)
return 0;
int slow=1;
int fast=1;
for(;fast<nums.length;fast++)
if(nums[fast]!=nums[fast-1])
nums[slow]=nums[fast];
slow++;
return slow;
二、买股票的最佳时机(122题)
原题如下:
给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例1:
输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出,
这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,
这笔交易所能获得利润 = 6-3 = 3 。
示例2:
输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
示例3:
输入: prices = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出,
这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,
你必须在再次购买前出售掉之前的股票。
1.动态规划
我研究了半天没研究明白,下次一定。
2.贪心算法
因为此题不规定我们出售和买入的次数,所以只要我们把所有的上升沿全部累加就可以得到最大利润了。但是这种解法的缺陷也很明显,他只能算出我们最终获得的利润,并不能准确的求出我们买入和售出的下标。
参考代码:
class Solution
public int maxProfit(int[] prices)
if(prices==null||prices.length<=1)
return 0;
int ret=0;
for(int i=0;i<prices.length-1;i++) //循环遍历每一天
if(prices[i]<prices[i+1]) //只要明天的价格大于今天的就卖出
ret+=prices[i+1]-prices[i];
return ret;
三、轮转数组(1868题)
原题如下:
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
1.使用额外数组
从新开辟一个数组用来存放移动之后的各个元素。这种方法需要开辟新的空间对内存的损耗较大,但是很容易想到。
其中我们会用到一个拷贝方法:
System中提供了一个native静态方法arraycopy(),可以使用这个方法来实现数组之间的复制。
System.arraycopy(Object srcArray,int srcPos,Object destArray ,int destPos,int length)
Object src : 原数组
int srcPos : 从元数据的起始位置开始
Object dest : 目标数组
int destPos : 目标数组的开始起始位置
int length : 要copy的数组的长度
参考代码:
class Solution
public void rotate(int[] nums, int k)
k=k%nums.length;
int n=nums.length;
int[]arr=new int[n];
for(int i=0;i<n;i++)
arr[(i+k)%n]=nums[i];
System.arraycopy(arr,0,nums,0,n);
2.翻转数组
首先我们知道移动数组长度次相当于没有移动,所以我们上来先把k对length取余得到有效移动次数。
我们只需要先将原来数组翻转一次,然后分别将前k个元素和其余元素再次翻转便可得到右移k次的新数组
参考代码:
class Solution
public void rotate(int[] nums, int k)
k=k%nums.length;
swap(0,nums.length-1,nums);
swap(0,k-1,nums);
swap(k,nums.length-1,nums);
public static void swap(int start,int end,int[] arr) //翻转方法
while(start<end)
int temp=arr[end];
arr[end]=arr[start];
arr[start]=temp;
end--;
start++;
思考:如果将右旋改为左旋则代码该如何修改?
四、存在重复元素(1898题)
给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
示例1:
输入: [1,2,3,1]
输出: true
示例2:
输入: [1,2,3,4]
输出: false
1.排序比对
先将数组排序,然后遍历数组比对相邻两个元素是否相等。
参考代码:
class Solution
public boolean containsDuplicate(int[] nums)
Arrays.sort(nums);
for(int i=1;i<nums.length;i++)
if(nums[i-1]==nums[i])
return true;
return false;
五、两个数组的交集 II(1505题)
给定两个数组,编写一个函数来计算它们的交集。
示例1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
1.双指针大法
先将两个数组进行排序
定义两个指针分别指向两个数组的头,如果指向的值相等则同时后移并记录,不相等则值较小的指针向后移动一位,当有一个数组遍历完则停止。
class Solution
public int[] intersect(int[] nums1, int[] nums2)
Arrays.sort(nums1);
Arrays.sort(nums2);
int len1=nums1.length;
int len2=nums2.length;
int[] arr = new int[Math.min(len1, len2)];
int a=0;int b=0;int c=0; //a指向len1,b指向len2,c指向放答案的数组arr
while(a<len1&&b<len2)
if(nums1[a]<nums2[b])
a++;
else if(nums1[a]>nums2[b])
b++;
else if(nums1[a]==nums2[b])
arr[c]= nums1[a];
a++;
b++;
c++;
return Arrays.copyOfRange(arr, 0, c);
我们不能直接输出arr因为arr的大小使我们两个数组中较小的内而过数组的长度,我们相等的元素个数可能没有那么多,这样就会出现输出的arr后面有0的情况,所以我们再输出的时候要使用Arrays.copyOfRange方法把0下标到c下标的元素输出。
如果直接return arr结果会无法通过所有的测试用例 (如下图) 。
介绍一下Arrays.copyOfRange方法
Arrays.copyOfRange(T[]arr,int start,int end)
复制arr数组从start下标复制到end下标
思考:如果将第三题轮转数组右旋改为左旋则代码该如何修改?
以上是关于LeetCode数组算法题(Java版)的主要内容,如果未能解决你的问题,请参考以下文章