LeetCode-数组

相关介绍

集合&列表&数组

集合

  • 集合中装载的元素类型不一定相同
  • 元素没有顺序

列表

列表是在集合的概念上形成的,是一种线性的数据集合,通常具有以下特征:

  • 元素按一定的顺序排列
  • 长度是可变的,可以向列表中添加/删除元素

表现形式:

  • 常见的表现形式是:链表和数组
  • 特殊的表现形式:栈和队列

数组

数组是列表的一种具体的表现形式,它的特点有:

  • 它与列表的最明显的不同就是引入了索引的概念
  • 数组中的元素在内存中是连续存储的,且每个元素占用相同大小的内存

数组的操作

1、读取元素

数组在内存中的存储方式是连续内存的方式,通常会记录下第一个元素的内存地址,然后通过第一个元素的内存地址+索引值的方式读取元素,时间复杂度为 O(1)。

2、查找元素

查找元素时要从头到尾挨个匹配,因此最坏时间复杂度为 O(n)。

3、插入元素

数组插入元素时,如果插入的位置正好是末尾,那么时间复杂度为O(1),但是首尾之间的情况就是插入后,后面的元素要整体后移一个单位,所以是O(n)。此时用链表是最合适的,时间复杂度为O(1)。

4、删除元素

删除元素,整体上要前移,所以为O(n)。

题目一

主站-1991. 找到数组的中间位置

给你一个下标从 0 开始的整数数组 nums ,请你找到 最左边 的中间位置 middleIndex (也就是所有可能中间位置下标最小的一个)。

中间位置 middleIndex 是满足 nums[0] + nums[1] + … + nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + … + nums[nums.length-1] 的数组下标。

如果 middleIndex == 0 ,左边部分的和定义为 0 。类似的,如果 middleIndex == nums.length - 1 ,右边部分的和定义为 0 。

请你返回满足上述条件 最左边 的 middleIndex ,如果不存在这样的中间位置,请你返回 -1 。

解题思路

  • 先遍历数组得到数组之和 sum;
  • 再遍历数组得到数组的左侧元素之和 left_sum,当 left_sum 的二倍加上当前元素的和等于 sum 时,满足条件直接返回;
  • 否则表示没有合适的元素,返回 -1;

代码及注释

class Solution {
            public int findMiddleIndex(int[] nums) {
                int sum = 0;
                for (int i = 0; i < nums.length; i++) {
                    sum += nums[i];
                }

                int left_sum = 0;
                for (int j = 0; j < nums.length; j++) {
                    if (left_sum * 2 + nums[j] == sum) {
                        return j;
                    }
                    left_sum += nums[j];
                }

                return -1;
            }
        }

题目二

主站-56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

解题思路

常规的思路就是我们拿到两个数组比较它的首尾元素,两边都取那个范围更大的值,但是这样就需要每拿到一个数组就跟前面的所有数组做对比,有些情况本来没有重叠的两个数组,加上另一个数组后反而有重叠了,所以还要从头至尾比较,时间复杂度比较高。

先将区间按照子数组的首元素排序,这样就可以只比较当前区间的末尾元素与比较区间的首尾元素即可,具体做法是:

  • 如果当前区间的末尾元素 < 比较区间的首元素时,说明没有交集,新开一个合并区间;
  • 比较当前区间的末尾元素 & 比较区间的尾元素,取一个大的作为合并区间末尾数值;

复制数组,返回结果

代码及注释

public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, new Comparator<int[]>() {
            @Override
            public int compare(int[] interval0, int[] interval1) {
                return interval0[0] - interval1[0];
            }
        });

        int[][] res = new int[intervals.length][2];
        int index = -1;

        for (int i = 0; i < intervals.length; i++) {
            if (index == -1 || res[index][1] < intervals[i][0]) {
                res[++index] = intervals[i];
            } else {
                res[index][1] = Math.max(res[index][1], intervals[i][1]);
            }
        }

        return Arrays.copyOf(res, index + 1);
    }

题目三

热题100-48. 旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

解题思路

假设矩阵中一个元素的位置为:(i,j), 对于矩阵中第 i 行的第 j 个元素,在旋转后,它出现在倒数第 i 列的第 j 个位置。 通过归纳,经过旋转后的位置为:(j,n-i-1)。那我们进行如下操作:

  • 先对矩阵进行水平翻转:(x,y)=(n-x-1,j)
  • 再对矩阵按主对角线翻转:(a,b)=(b,a)

因此经过两次翻转后的坐标应该是:(x,y)=(y,n-x-1),正好就是旋转90°的坐标

代码及注释

class Solution {
    public void rotate(int[][] matrix) {//matrixnew​[col][n−row−1]=matrix[row][col]
    int n=matrix.length;
    for(int i=0;i<n/2;i++){
        for(int j=0;j<n;j++){
            int temp=matrix[i][j];
            matrix[i][j]=matrix[n-i-1][j];
            matrix[n-i-1][j]=temp;
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<i;j++){
            int temp=matrix[i][j];
            matrix[i][j]=matrix[j][i];
            matrix[j][i]=temp;
        }
    }
    }
}

题目四

73. 矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

解题思路

  • 可以遍历矩阵,遇到 0 时就进入一个方法将所在的行、列置零,但是有个问题就是最后都为 0 了,就没法区分是置零产生的还是矩阵中原有的;
  • 还有一种方法就是通过标志位矩阵来记录出现零的具体位置,这种方法的空间复杂度还可以优化,因为这里不论矩阵中一行(一列)有几个零,所在的行(列)都要置零,那么我们不需要记录准确的位置,只需要记录行(列)出现过零就可以;
  • 那么就可以通过一个行、列标志向量来记录哪一行或者哪一列出现过零就可以,然后再遍历矩阵将对应的行或者列置零就可以。

代码及注释

public class Solution {
    public void SetZeroes(int[][] matrix) {
        bool[] row = new bool[matrix.Length];
        bool[] column = new bool[matrix[0].Length];
        for (int i = 0; i < matrix.Length; i++) {
            for (int j = 0; j < matrix[0].Length; j++) {
                if (matrix[i][j] == 0) {
                    row[i] = true;
                    column[j] = true;
                }
            }
        }
        for (int i = 0; i < matrix.Length; i++) {
            for (int j = 0; j < matrix[0].Length; j++) {
                if (row[i] || column[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值