LeetCode刷题-数组-2

1.买卖股票的最佳时机II

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

解题思路:
如果后一天的股票值大于前一天,就把股票卖掉,累计利润就是最大利润。

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

运行结果:
在这里插入图片描述

2.两数之和II

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

解题思路:
设置两个指针p1和p2,分别指向数组的头和尾,当头加尾的值大于目标值,则p2–;当头加尾的值小于目标值,则p1++;如果恰好等于目标值,则返回头尾指针加1的值,因为下标值是从1开始的。

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int low = 0;
        int high = numbers.length-1;

        int[] nums = new int[2];

        while(low < high){
            if(numbers[low] + numbers[high] > target){
                high--;
            }else if(numbers[low] + numbers[high] < target){
                low++;
            }else{
                nums[0] = low+1;
                nums[1] = high+1;
                break;
                
            }
        }

        return nums;
    }
}

运行结果:
在这里插入图片描述

3.多数元素

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

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

解题思路:
维护一个候选众数 result和它出现的次数 count。初始时 result设为nums[0],count 为 1;遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 result,随后我们判断 x:如果 x 与 result相等,那么计数器 count 的值增加 1;如果 x 与 result不等,那么计数器 count 的值减少 1。在遍历完成后,result即为整个数组的众数。将count重新设置为0,遍历数组,计算result的出现次数,如果出现次数乘2大于数组长度,那么就返回result,否则返回0。

class Solution {
    public int majorityElement(int[] nums) {
       int count = 1;
       int len = nums.length;
       int result = nums[0];

       for(int i = 1;i < len;i++){
           if(count == 0){
               result = nums[i];
               count++;
           }else{
               if(nums[i] == result){
                   count++;
               }else{
                   count--;
               }
           }
       }

        count = 0;
        for(int i = 0;i < len;i++){
            if(result == nums[i]){
                count++;
            }
        }

        if(count * 2 <= len){
            result = 0;
        }
        return result;
    }
}

运行结果:
在这里插入图片描述

4.旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

解题思路:
借助一个新的数组。

class Solution {
    public void rotate(int[] nums, int k) {
        int[] a = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            a[(i + k) % nums.length] = nums[i];
        }
        for (int i = 0; i < nums.length; i++) {
            nums[i] = a[i];
        }
        
    }
}

运行结果:
在这里插入图片描述

5.存在重复元素

给定一个整数数组,判断是否存在重复元素。

如果任意一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。

解题思路:
用map保存数组中的值和它的次数,遍历数组,如果map中已经包含了某个值,返回true,结束遍历;否则将该值和其出现次数加入map。

import java.util.*;
class Solution {
    public boolean containsDuplicate(int[] nums) {
        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
        boolean result = false;

        for(int i = 0;i < nums.length;i++){
            if(map.containsKey(nums[i])){
                result = true;
                break;
            }else{
                map.put(nums[i], 1);
            }
        }

        return result;

    }
}

运行结果:
在这里插入图片描述

6.存在重复元素II

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

解题思路:
用map保存数组中的值和它的索引,遍历数组,如果map中已经包含了某个值,判断两者的索引差的绝对值是否大于k,如果大于k,将该值和现在的索引重新放入map中。

import java.util.HashMap;
import java.util.Map;
class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
        boolean result = false;
        for(int i = 0;i < nums.length;i++){
            if(map.containsKey(nums[i])){
                if(Math.abs(map.get(nums[i]) - i ) <= k){
                    result = true;
                    break;                 
                }else{
                    map.put(nums[i], i);
                }
            }else{
                map.put(nums[i], i);
            }

        }
        return result;

    }
}

运行结果:
在这里插入图片描述

7.缺失数字

给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。 解题思路:

思路1:
先将数组进行排序。判断数组第一个数组是否为0 ,不为0,缺失的数字为0;判断数组最后一个数字是否为n,不为n,则缺失的数字为n。第三种情况判断任意中间两个相邻数的差是否大于1,若大于1,则返回前一个数+1的值或者后一个数减1的值。

class Solution {
    public static int missingNumber(int[] nums) {
        int result = 0;
        Arrays.sort(nums);

        if(nums[nums.length-1] != nums.length){
            result = nums.length;
        }
        if(nums[0] != 0){
            result = 0;
        }

        for(int i = 0;i < nums.length-1;i++){
            if(nums[i+1]-nums[i]>1){
                result = nums[i] + 1;

            }
        }

        return result;

    }
}

运行结果:
在这里插入图片描述
思路2:用高斯求和公式求出0到n的和,然后减去数组的和,就是缺失的数字。

class Solution {
    public static int missingNumber(int[] nums) {
        int sum = nums.length * (nums.length+1) / 2;
        int actSum = 0;
        for(int num:nums){
            actSum += num;
        }
        int result = sum-actSum;

        return result;

    }
        
}

运行结果:
在这里插入图片描述

8.移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
说明:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。

解题思路:
用0当做中间点,把不等于0的放到中间点的左边,等于0的放到其右边。我们使用两个指针i和p1,只要nums[i]!=0,我们就交换nums[i]和nums[p1]。

class Solution {
    public void moveZeroes(int[] nums) {
        int p1 = 0;
        for(int i = 0;i < nums.length;i++){
            if(nums[i] != 0){
                int temp = nums[i];
                nums[i] = nums[p1];
                nums[p1++] = temp;
            }
        }


    }
}

运行结果:
在这里插入图片描述

9.第三大的数

给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。

解题思路:
利用TreeSet实现。TreeSet是有序的Set集合。设置TreeSet的大小为3,保存三个最大的数。如果数组长度小于3,返回最大值,如果大于3,返回TreeSet中的第一个值。

class Solution {
    public int thirdMax(int[] nums) {
        TreeSet<Integer> set = new TreeSet<>();

        for(Integer num:nums){
            set.add(num);
            if(set.size()>3){
                set.remove(set.first());
            }
        }

        return set.size()<3?set.last():set.first();

        

    }
}

运行结果:
在这里插入图片描述

10.找到所有数组中缺失的数据

给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。 找到所有在 [1, n] 范围之间没有出现在数组中的数字。

您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

解题思路:
将数组中的每个数字对应一个下标,比如数字3对应下标2,并且把下标2上的数字变为负数,这样,最后哪个下标上的数字为正,就说明缺(下标+1)这个数字。
在这里插入图片描述

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {

        for(int i = 0;i < nums.length;i++){
            int newIndex = Math.abs(nums[i])-1;
            if(nums[newIndex] > 0){
                nums[newIndex] *= -1;
            }
        }

        List<Integer> list = new LinkedList<Integer>();

        for(int i = 0;i < nums.length;i++){
            if(nums[i] > 0){
                list.add(i+1);
            }
        }

        return list;

    }
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值