首页 > 其他分享 >LeetCode - 数组的改变和移动

LeetCode - 数组的改变和移动

时间:2022-09-24 23:26:43浏览次数:75  
标签:nums int 元素 min 数组 移动 LeetCode left

1. 数组的改变和移动总结

1.1 数组的改变

数组在内存中是一块连续的内存空间,我们可以直接通过下标进行访问,并进行修改。

Java中,对于List类型来说,我们可以通过set(idx, element)方法将idx位置的元素进行修改。

1.2 数组的移动

数组的移动不能通过一条语句来实现,通常来说需要通过:插入、删除或者多次交换来实现。

1.3 数组的插入

数组的插入比较麻烦,我们想要在下标为k的位置插入一个元素时,首先需要将k及以后的元素往后移动一个位置,然后再将元素插入到k的位置处。

Java中,对于List类型来说,我们可以通过add(idx, element)方法将元素添加到idx下标处。

1.4 数组的删除

删除下标为k的元素时,需要将k以后的元素向前移动一个位置。

对于List类型来说,我们可以通过remove(idx)方法删除下标为idx的元素。

2. 题目记录

453. ⭐最小操作次数使数组元素相等

分析题意

给你一个长度为 n的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。

思路分析

这道题有一个很巧妙的思路:由于我们并不关心最终元素相等时的值而只关心操作的次数。所以我们可以将上述问题转化为:每次操作使一个元素减少1,返回让数组中所有元素相等的最小操作数。这样就简单了:我们想要操作数最小,就必须找到能使所有元素相等的最小值,其实这个值就是数组中的最小值。而操作的次数就是:每个数与最小值的差值之和。

class Solution {
    public int minMoves(int[] nums) {
        int min = Integer.MAX_VALUE;

        for(int i = 0; i < nums.length; i++){
            min = Math.min(nums[i], min);
        }

        int ans = 0;
        for(int i = 0; i < nums.length; i++){
            ans = ans + nums[i] - min;
        }

        return ans;

    }
}

那么正向思考这个问题应该怎么做呢?

注意到:每次操作都使n-1个数加1,也就是所每次操作都会使该数组的sum加上n-1。假设最小操作数为a次,那么此时一定有数学关系式:\(a(n-1) + sum = nx\),其中x为最终数组中的值。

仅有这一个关系式的约束是不够的,我们还要想清楚的一点就是:原数组中最小的那个数需要操作a次才能够变为x ,即:\(min + a = x\) (这个比较难想明白)

根据这两个公式我们就可以求出最终的a了:\(a = sum - n * min\)

class Solution {
    public int minMoves(int[] nums) {
        int min = Integer.MAX_VALUE;
        int sum = 0;

        for(int i = 0; i < nums.length; i++){
            sum += nums[i];
            min = Math.min(nums[i], min);
        }
        return sum - nums.length * min;

    }
}

复杂度分析

时间复杂度:O(n)

空间复杂度:O(1)

665. 非递减数列

分析题意

给你一个长度为 n 的整数数组 nums,请你判断在最多改变 1 个元素的情况下,该数组能否变成一个非递减数列。

思路分析

从前往后遍历,找到第一个 a > b的情况时,对ab 的值进行修改,然后判断修改后的数组是否为非递减数组即可。关键在于:修改 a 还是 修改 b 呢?

这里其实是有两个选择的:

  1. 对于 [1, 3, 4, 2, 5] ,此时应该修改 b
  2. 对于[1, 3, 4, 3, 4], 此时应该修改 a

一种简单的方法就是:我们两种情况都尝试,看看是否能够得到非递减数组。

class Solution {
    public boolean checkPossibility(int[] nums) {

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

                // 修改a
                nums[i] = n_2;
                if(checkMethod(nums)) return true;

                // 复位a
                nums[i] = n_1;
                // 修改b
                nums[i + 1] = n_1;
                if(checkMethod(nums)) return true;

                return false;
            }
        }
        return true;
    }

    boolean checkMethod(int[] nums){
        for(int i = 1; i < nums.length; i++){
            if(nums[i - 1] > nums[i]) return false;
        }

        return true;
    }
}

复杂度分析

时间复杂度:O(n)

空间复杂度:O(1)

283. 移动零

分析题意

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

关键点:保持非零元素的相对顺序。

思路分析

首先排除首尾双指针的思路,因为要保持非零元素的相对顺序,所以不能够使用首尾双指针来做。

首尾双指针是指:左指针找第一个0元素,右指针找第一个非0元素,然后交换两个元素。有点像归并排序。

由于不复制数组,所以大概率还是使用双指针来操作。分析一下,假设我们知道left左侧都是非零元素,然后在left右侧找到了一个非零元素,此时只需要将该元素放在left下标下即可。

基于此思路,我们用left来标识已经处理元素的右边界,然后通过右指针去寻找下一个非0元素,找到后放置在left位置并将left指针右移。

class Solution {
    public void moveZeroes(int[] nums) {
        int left = 0;
        int right = 0;

        while(right < nums.length){
            if(nums[right] != 0){
                nums[left] = nums[right];
                left ++;
            }

            right ++;
        }

        while(left < nums.length){
            nums[left] = 0;
            left ++;
        }

    }
}

复杂度分析

时间复杂度:O(n)

空间复杂度:O(1)

标签:nums,int,元素,min,数组,移动,LeetCode,left
From: https://www.cnblogs.com/404er/p/array_move.html

相关文章

  • 数组的各种方法
    数组的各种方法:push、unshift都是给数组添加元素,都可以接受多个参数,都会返回添加后的目标数组的长度。前者从数组结尾添加,后者从数组开头处添加。pop、shift都是从数组处......
  • leetcode 669. Trim a Binary Search Tree 修剪二叉搜索树 (简单)
    一、题目大意给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉搜索树,使得所有节点的值在[low,high]中。修剪树不应该改变保留在树中的......
  • leetcode40-组合总和 II
    40.组合总和II 这题和 39.组合总和 差不了多少。区别就是这一题提供的集合内有重复元素,而上一题没有重复元素。因为有重复元素,所以输出的结果里不能有重复的中间......
  • 力扣1095——山脉数组中查找目标值
    1095.山脉数组中查找目标值难度困难(这是一个 交互式问题 )给你一个 山脉数组 mountainArr,请你返回能够使得 mountainArr.get(index) 等于 target 最小 的......
  • 数组处理方法总结
    今天遇到了一个操作数组的问题,概念有点模糊,整理一下。some()作用:判断是否有元素符合func条件,返回一个Boolean不会修改原数组constarr=[1,2,3,4];arr.some((item)=......
  • leetcode39-组合总和
    39.组合总和 首先是原始的错误代码classSolution{public:intsize,sum=0;vector<vector<int>>res;vector<int>path;voidbackTracking(ve......
  • 四 Java数组
    Java数组数组的定义数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个数组元素,每个数组元......
  • TypeScript Array数组 生成两个数组的交集,并且在数组中进行删除操作
    TypeScriptArray数组 生成两个数组的交集,并且在数组中进行删除操作 /***@methodcutArr删除数组1中,与数组2重复的数据*Arr([1,2,3,5],[2,3,4])=>[1,5......
  • TypeScript Array 数组 两个数组取交集
    TypeScriptArray数组两个数组取交集   //取交集  privateArrayIntersection(a,b)  {    varai=0,bi=0;    varresult=new......
  • leetcode 311场周赛总结
    1、最小偶倍数(2413)题目:给你一个正整数n,返回2和n的最小公倍数(正整数)。签到题,奇数的话就*2,偶数直接返回。classSolution{public:intsmallestEvenMultip......