当前位置: 首页 > news >正文

数组总结【代码随想录】

一.数组

1.lc 27移除数组中的重复元素

且必须仅使用 O(1) 额外空间并 原地 修改输入数组

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案

public static int removeElement(int[] nums, int val) {
        int i = 0;
        int len = nums.length;
       while (i<len){
           if (nums[i]==val){
               nums[i] = nums[len-1];
               len--;
           }else {
               i++;
           }
       }
        return len;
    }

总结:直接输出移除指定元素后的数组长度是非常容易的,原地修改数组需要:如果第一个元素是指定的元素,那么我们将最后一个元素的值赋给第一个元素并且len指针往前移(逻辑上把指定元素删了,数组长度减1)。

2.lc977 有序数组的平方

你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

public class Case977 {
    public static void main(String[] args) {
        int[] nums = {-4,-1,0,3,10};
        //返回数组内容的字符串表示形式
        System.out.println(Arrays.toString(sortedSquares(nums)));
    }
    public static int[] sortedSquares(int[] nums) {
        int len = nums.length;
        for (int i = 0; i < nums.length; i++) {
            nums[i] = (int) Math.pow(nums[i],2);
        }
        Arrays.sort(nums);
        return nums;
    }
}

总结:利用api快速解题,时间复杂度为O(nlogn)。再学一招:双指针!O(n) 思路:数组有序,那么数组元素平方后,最大值只可能在两边,不可能在中间,如{-5,-4,-3,-2,-1,0,1},所以可以用双指针进行解答。

public static int[] sortedSquares2(int[] nums) {
    int n = nums.length;
    int[]res = new int[n];
    int i = 0;
    int j = n-1;
    int k = n-1;
   while (i<=j){
       if (nums[i]*nums[i] < nums[j]*nums[j]){
           res[k--] = nums[j]*nums[j];
           j--;
       }else {
           res[k--] = nums[i]*nums[i];
           i++;
       }
   }
   return res;
}

3.lc209【middle】 求长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target的长度最小的连续子数组 并返回其长度,如果不存在符合条件的子数组,返回 0 。

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

思路1:暴力,是最容易想到的方法,但超时了。时间复杂度为O(n*n)

public static int minSubArrayLen(int target, int[] nums) {
    int min = Integer.MAX_VALUE;
    for (int i = 0; i < nums.length; i++) {
        int sum = nums[i];
        if (sum >= target) return 1;
        for (int j = i + 1; j < nums.length; j++) {
            sum += nums[j];
            if (sum >= target) {
                min = Math.min(min, j - i + 1);
                break; //发现符合情况的,没必要往后加了,直接跳出本次循环。
            }
        }
    }
    return min==Integer.MAX_VALUE ? 0:min;
}

思路2:滑动窗口。时间复杂度为O(n),这种滑动窗口的类型是先找到符合条件的子数组,如果找不到往后拓展窗口的长度,直到找到为止(可能>>target),后改变起始位置,缩小滑动窗口。

public static int minSubArrayLen2(int target, int[] nums) {
    int left = 0;
    int sum = 0;
    int res = Integer.MAX_VALUE;
    //j 表示的是滑动窗口的终止位置。那么起始位置需要我们自己去调。
    for (int right = 0; right <nums.length ; right++) {
        sum += nums[right];
        while (sum>=target){
            res = Math.min(res,right-left+1);
            sum-=nums[left++];
        }
    }
    return res==Integer.MAX_VALUE?0:res;
}

4.删除有序数组中的重复项。

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

public static int removeDuplicates(int[] nums) {
   int i = 0;
   for (int j = 1; j < nums.length; ) {
        if (nums[i]!=nums[j]){
             i++;
             nums[i] = nums[j];
            }else {
               j++;
            }
        }
        return i+1;
}

5.搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。

输入: nums = [1,3,5,6], target = 5
输出: 2

public static int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
while (left<=right){
    int mid = (left+right)/2;
    if (nums[mid]<target){
        left = mid+1;
    }else if (nums[mid] >target){
        right = mid-1;
    }else {
        return mid;
    }
}
return left;
}

 思路:看见题目要求时间复杂度为O(logn)必然要想到二分查找!但前提是数组有序,接下来就是在二分查找模板的基础上进行改动!

6.合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1nums2,另有两个整数 mn ,分别表示 nums1nums2 中的元素数目。请你 合并 nums2nums1 中,使合并后的数组同样按 非递减顺序 排列。

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

 思路一:利用api,快速解题,时间复杂度为O((n+m)log(m+n))

public static void merge(int[] nums1, int m, int[] nums2, int n) {
//        for (int i = 0; i!=n ; i++) {
//            nums1[m+i] = nums2[i];
//        }
        System.arraycopy(nums2,0,nums1,m,n);
        Arrays.sort(nums1);

思路2:开辟一个一个辅助数组。时间复杂度O(n),空间复杂度O(n+m)。

public static void merge2(int[] nums1, int m, int[] nums2, int n) {
    int[]temp = new int[m];
    System.arraycopy(nums1,0,temp,0,m);//把nums1里面的元素,下标从0开始复制到temp里,下标从0开始,复制m个数。
    int p1 = 0;  //指向temp
    int p2 = 0;  //指向nums2
    int p = 0;   //指向nums1的开头
    while ((p1<m)&&(p2<n)){
        nums1[p++] = temp[p1]<nums2[p2] ? temp[p1++] : nums2[p2++];
    }
    if (p1<m) System.arraycopy(temp,p1,nums1,p1+p2,m+n-p1-p2);
    // 如果p1走完的时候,p2还没走完,则把nums2从下标为p2的元素全部复制到nums1,复制m+n-p1-p2个元素
    if (p2<n) System.arraycopy(nums2,p2,nums1,p1+p2,m+n-p1-p2); 
}
class Solution {
    public void merge(int[] A, int m, int[] B, int n) {
        for (int i = 0; i != n; ++i) {
            A[m + i] = B[i];
        }
        Arrays.sort(A);
    }
}

7.螺旋矩阵I [middle]

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

例如:

 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

思路:依次从左往右,从上到下,从右往左,从下往上依次遍历。

List<Integer> list = new ArrayList<>();
int left = 0;
int right = matrix[0].length-1; //列数
int up = 0;
int down = matrix.length-1;  //行数
while (true){
    //左——>右
    for (int j = left; j <=right ; j++) {
        list.add(matrix[up][j]);
    }
    //第一行遍历完毕,开始遍历下面。
    if (++up>down){
        break;
    }
    //从上往下
    for (int i = up; i <= down; i++) {
        list.add(matrix[i][right]);
    }

    if (--right<left){
        break;
    }
    //从右往左
    for (int j = right; j>=left ; j--) {
        list.add(matrix[down][j]);
    }
    if (--down<up){
        break;
    }
    //从下往上
    for (int i = down; i >=up ; i--) {
        list.add(matrix[i][left]);
    }
    if (++left>right){
        break;
    }
}
return list;
}

8.螺旋矩阵||

你一个正整数 n ,生成一个包含 1n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

 思路:与螺旋矩阵I 模板一模一样,无非定义一个变量num,初始值为1,在每个循环体里面自增。

9.返回数组中正整数数目与负整数数目中的最大值

给你一个按 非递减顺序 排列的数组 nums ,返回正整数数目和负整数数目中的最大值。换句话讲,如果 nums 中正整数的数目是 pos ,而负整数的数目是 neg ,返回 posneg二者中的最大值。

nums = [-3,-2,-1,0,0,1,2]
输出:3
解释:共有 2 个正整数和 3 个负整数。计数得到的最大值是 3 

public static int maximumCount(int[] nums) {
    int len = nums.length;
    int cntNeg = negNum(nums) + 1;
    int cntPos = len-posNum(nums);
    return Math.max(cntNeg, cntPos);
}

private static int negNum(int[] nums) {
    //二分,求负数的个数。
    int i = 0;
    int j = nums.length - 1;
    while (i <= j) {
        int mid = (i + j) / 2;
        if (nums[mid] < 0) {
            i = mid + 1;
        } else {
            j = mid - 1;
        }
    }
    return j;
}
private static int posNum(int[] nums) {
    //二分,求负数和0的个数。
    int i = 0;
    int j = nums.length - 1;
    while (i <= j) {
        int mid = (i + j) / 2;
        if (nums[mid] >=1 ) {
            j = mid - 1;
        } else {
            i = mid+1;
        }
    }
    return i;
}

10.区间和

相关文章:

  • Docker数据卷操作实战
  • centos22.04 dpkg -l 输出状态标识含义
  • HTTP非流式请求 vs HTTP流式请求
  • 金融行业专题|某基金公司基于超融合信创平台支持人大金仓数据库的性能评测
  • 深入解析Tomcat目录结构
  • Grok 3 vs. DeepSeek vs. ChatGPT:2025终极AI对决
  • 【MATLAB中的图像数据结构】
  • 【奥卡姆剃刀原理-如何理解云计算和边缘计算 关键字摘取】
  • MATLAB下载安装教程(附安装包)2025最新版(MATLAB R2024b)
  • 网络安全之日志审计 网络安全审计制度
  • 山东大学软件学院ai导论实验之生成对抗网络
  • 【Python爬虫(71)】用Python爬虫解锁教育数据的奥秘
  • obj离线加载(vue+threejs)+apk方式浏览
  • DDNS-GO 动态域名解析
  • 基于YOLO11深度学习的医学X光骨折检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】
  • 基于SpringBoot的“洪涝灾害应急信息管理系统”的设计与实现(源码+数据库+文档+PPT)
  • 【Java】I/O 流篇 —— 转换流与序列化流
  • 5分钟学习-什么事前端HTML文件
  • Python 网络爬虫实战全解析:案例驱动的技术探索
  • Linux-IPC-消息队列
  • 李勇已任内蒙古乌兰察布市委副书记,曾在中央编办任职
  • 清华姚班,正走出一支军团
  • 新干式二尖瓣瓣膜国内上市,专家:重视瓣膜病全生命周期管理
  • 广州多条BRT相关线路将停运,全市BRT客运量较高峰时大幅下降
  • 释新闻|印度宣布“掐断”巴基斯坦水源,对两国意味着什么?
  • “养老规划师”实则售卖保险,媒体:多部门须合力整治乱象