栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

LeetCode数组算法题(Java版)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

LeetCode数组算法题(Java版)

文章目录
  • 一、删除有序数组中的重复项(26题)
    • 1.双指针解法
  • 二、买股票的最佳时机(122题)
    • 1.动态规划
    • 2.贪心算法
  • 三、轮转数组(1868题)
    • 1.使用额外数组
    • 2.翻转数组
  • 四、存在重复元素(1898题)
    • 1.排序比对
  • 五、两个数组的交集 II(1505题)
    • 1.双指针大法

一、删除有序数组中的重复项(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 
二、买股票的最佳时机(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 
三、轮转数组(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 
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 

思考:如果将右旋改为左旋则代码该如何修改?

四、存在重复元素(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 
五、两个数组的交集 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(anums2[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下标

思考:如果将第三题轮转数组右旋改为左旋则代码该如何修改?

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/571498.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号