A、力扣刷题——数组

news2025/7/22 23:11:46

提示:这是力扣上数组类题目里的简单题,按顺序做下来的23道题。

第一题: 

关键词:原地修改,有序数组 

我的答案: (for循环)

(1)有序数组

class Solution{
    public int removeDuplicates(int[] nums){
        int k=1;//新数组从第二个元素开始覆盖式加入
        for(int i=1;i<nums.length;i++){//从第二个元素开始与前面的元素比较
                //因为数组是有序排列,所以只需要判断该元素是否与前一个元素相同即可
                if(nums[i]==nums[i-1]){
                    continue;
                }else{//与前面的数组没有相同的元素,覆盖式加入
                    nums[k++]=nums[i];
                }
        }
        return k;//返回已经删除重复元素的数组长度,只取出原数组的前k位,既得“删除”之意
    }
}

 (2)无序数组

class Solution{
    public int removeDuplicates(int[] nums){
        int k=1;
        for(int i=1;i<nums.length;i++){
            //遍历前面的元素,
            for(int j=0;j<i;j++){
                //若前面已经存在相同的元素,即刻放弃该元素,取下一个元素判断
                if(nums[i]==nums[j]){
                    continue;
                }else if(j==i-1){//若已经比较到该元素的前一个元素,都没有相同的,则覆盖式加入原数组
                    nums[k++]=nums[i];
                }
            }
        }
        return k;
    }
}

 官方答案:(双指针)

class Solution {
    public int removeDuplicates(int[] nums) {
        int n = nums.length;
        //空数组,直接返回
        if (n == 0) {
            return 0;
        }
        //快指针用于扫描原数组,慢指针用于存放元素
        int fast = 1, slow = 1;
        while (fast < n) {
            //该元素与前一个元素不相同,则加入
            if (nums[fast] != nums[fast - 1]) {
                nums[slow] = nums[fast];
                ++slow;
            }
            ++fast;
        }
        return slow;//返回新数组长度
    }
}

第二题:

 我的答案:

(1)普通解法

class Solution {
    public int removeElement(int[] nums, int val) {
        int k=0;
        //遍历数组的元素
        for(int i=0;i<nums.length;i++){
            if(nums[i]!=val){//如果不等于val,则覆盖式加入原数组
                nums[k++]=nums[i];
            }
        }
        return k;//返回新数组的长度
    }
}

代码优化(画手大鹏,for循环挺高级的,有点帅):

class Solution {
    public int removeElement(int[] nums, int val) {
        int ans = 0;
        for(int num: nums) {
            if(num != val) {
                nums[ans] = num;
                ans++;
            }
        }
        return ans;
    }
}

 (2)双指针(元素都往前移,填补值等于val的元素的空白,元素的顺序不变)

class Solution {
    public int removeElement(int[] nums, int val) {
        int n=nums.length;
        if(n==0){
            return 0;//数组为空,直接返回
        }
        //快指针用于遍历元素,慢指针用于存放筛选后的元素
        int fast=0,slow=0;
        while(fast<n){//当fast=n时,即为已经遍历了原数组
            if(nums[fast]!=val){
                nums[slow++]=nums[fast];//存放筛选后的元素
            }
            fast++;
        }
        return slow;//返回新数组长度
    }
}

 官方答案:(双指针,直接取数组最后的元素来填补前面的空白,元素顺序错乱)

class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0;//左指针位于数组的头部
        int right = nums.length;//右指针位于数组的尾部
        while (left < right) {//当left==right时,已经遍历了原数组
            if (nums[left] == val) {
                nums[left] = nums[right - 1];//如果left值为val,则取(复制)最后一个元素的值来覆盖它,右指针往前移一步。然后重新判断left的值是否等于val,如果还是等于,就再次重复上述步骤
                right--;//右指针往前移
            } else {
                left++;//左指针往后移
            }
        }
        return left;//返回新数组的长度
    }
}

第三题

 我的答案(逐个查找): 

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n=nums.length;//数组长度
        for(int i=0;i<n;i++){
            if(nums[i]==target){//找到与目标值相同的元素
                return i;//返回元素的位置
            }else if(nums[i]>target){//测试数组是升序数组,如果发现比目标值高的就停下(前面的都是比目标值矮的),插队
                return i;
            }
        }
        return n;//整个数组都没有比目标值高的元素,所以目标值插在最后的位置,下标值正好等于数组的长度值n
        
    }
}

  官方答案(二分查找法):

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
        int left = 0, right = n - 1, ans = n;//ans 初值设置为数组长度可以省略边界条件的判断,因为存在一种情况是target 大于数组中的所有数,此时需要插入到数组长度的位置。
        while (left <= right) {//数组有奇数个元素(中间只有一个元素)就用=,有偶数个元素(中间有两个元素)就用<。从两边往中间逼近,最后一个元素的表达方式
            int mid = ((right - left) >> 1) + left;
            // >> 1 是二进制的数字向右移一位,即除以2的意思
            //mid 表示left和right的中间位置的下标,得到两个等分的部分
            if (target <= nums[mid]) {//如果target大于mid,则只需要比较后半部分即可,否则就比较前半部分即可。如果target = nums[mid],则表示找到了目标值的下标,下面用ans返回下标即可
                ans = mid;//统一用ans返回
                right = mid - 1;//mid已经和target比较过了,所以往旁边挪一步,继续找
            } else {
                left = mid + 1;
            }
        }
        return ans;//返回中间的位置,最终筛剩的位置
    }
}

 

 网友答案(相较于官方的答案,去掉了ans变量):

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
        int l=0,r=n-1;
        while(l<=r){
            int mid=l+(r-l)/2;
            if(nums[mid]<target)
                l=mid+1;
            else r=mid-1;
        }
        return l;
    }
}

第四题

我没写出来

官方答案:

class Solution {
    public int[] plusOne(int[] digits) {
        int n = digits.length;//数组的长度
        for (int i = n - 1; i >= 0; --i) {//从后往前看,逆序遍历
            if (digits[i] != 9) {
                ++digits[i];//第一种情况:digits 最后一位不是9,直接加1
                for (int j = i + 1; j < n; ++j) {//前面加1了,把后面的连续几位的9全部置为0(属于第二种情况)
                    digits[j] = 0;
                }
                return digits;
            }//第二种情况:digits 后面连续几位数字是9,则往前找到第一不是9的数字,加1,后面全部置为0
        }

        //第三种情况:digits 中所有的元素均为 9
        int[] ans = new int[n + 1];//构造一个新数组
        ans[0] = 1;//新数组的第一位置为1,后面默认全部为0
        return ans;
    }
}

我困惑的点在于第三种情况,进位后,数组长度超出一位没想到要构建一个新数组。

网友更简洁的答案:

class Solution {
    public int[] plusOne(int[] digits) {
        for (int i = digits.length - 1; i >= 0; i--) {
            digits[i]++;
            digits[i] = digits[i] % 10;//如果取余得到0(意味着该位数之前是9),则再往前走一位来加1,
            if (digits[i] != 0) return digits;
        }
        digits = new int[digits.length + 1];
        digits[0] = 1;
        return digits;
    }
}

第五题

  我的答案(运行失败): 

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int k=m>n?n:m;//找到最短的数组
        for(int i=0;i<k;){
            for(int j=0;j<k;){
                if(nums1[i]>nums2[j]){
                    //数组1未比较的元素全部往后移一位,为了插入数组2的元素
                    j++;
                }else if(nums1[i]==nums2[j]){
                    j++;
                    i++;
                }else if(nums1[i]<nums2[j]){
                    //不用插入数组2的元素,所以数组1不用挪位,而且继续用该元素
                    i++;
                }
            }
        }
        if(m<n){
            for(int i=m;i<m+n;i++){
                nums1[i]=nums2[k++];
            }
        }
    }
}
//1、找到最短数组,比较两个数组相同长度的部分,两个指针
//2、比较数组1和数组2最前面的数,分三种情况:>,<,==,移动指针
//4、把最小值排好,然后这次比较的最大值继续与另一个数组的元素进行比较
//5、把较长数组后面多出的部分直接加入到数组1的后面(如果数组1长,则跳过这步)

 官方答案:

法一:直接合并后排序

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        for (int i = 0; i != n; ++i) {
            nums1[m + i] = nums2[i];//把数组2的全部元素放到数组1的后面
        }
        Arrays.sort(nums1);
    }
}

法二:双指针

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int p1 = 0, p2 = 0;//两个指针均指向两个数组的头部
        int[] sorted = new int[m + n];//创建一个新数组
        int cur;//定义一个中间变量
        while (p1 < m || p2 < n) {
            if (p1 == m) {//数组1比较短
                cur = nums2[p2++];//直接把数组2后面比数组1多出的部分加到排好序的新数组里
            } else if (p2 == n) {//数组2比较短
                cur = nums1[p1++];//直接把数组1后面比数组2多出的部分加到排好序的新数组里
            } else if (nums1[p1] < nums2[p2]) {//元素比较,把较小的加到新数组里
                cur = nums1[p1++];
            } else {
                cur = nums2[p2++];
            }
            sorted[p1 + p2 - 1] = cur;//把元素插进新数组
        }
        for (int i = 0; i != m + n; ++i) {//把新数组里合并好的元素全部转移到数组1里
            nums1[i] = sorted[i];
        }
    }
}

法三:逆向双指针

/*nums1的后半部分是空的,可以直接覆盖而不会影响结果。因此可以指针设置为从后向前遍历,每次取两者之中的较大者放进nums1的最后面。*/
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int p1 = m - 1, p2 = n - 1;//两个指针均指向两个数组的尾部
        int tail = m + n - 1;
        int cur;//临时变量
        while (p1 >= 0 || p2 >= 0) {
            if (p1 == -1) {//数组1较短
                cur = nums2[p2--];//把数组2前面比数组1多出的部分直接加到数组1里
            } else if (p2 == -1) {//数组2较短
                cur = nums1[p1--];//把数组1前面比数组2多出的部分直接加到数组1里
            } else if (nums1[p1] > nums2[p2]) {//元素比较,把较大值插入数组1的后面,从后往前
                cur = nums1[p1--];
            } else {
                cur = nums2[p2--];
            }
            nums1[tail--] = cur;
        }
    }
}
//我也是原地修改,但我是从前往后插入,所以面临着数组1前面的元素被覆盖的麻烦

第六题

   我的答案: 

class Solution {//双指针法,对撞指针
    public String reverseVowels(String s) {
        StringBuffer s1=new StringBuffer(s);//String里的值不能更改,所以转换成StringBuffer类
        char t;//定义一个变量,方便后面交换元素
        for(int i=0,j=s1.length()-1;i<j;i++){//前指针
            if(s1.charAt(i)=='a'||s1.charAt(i)=='i'||s1.charAt(i)=='e'||s1.charAt(i)=='u'||s1.charAt(i)=='o'||s1.charAt(i)=='A'||s1.charAt(i)=='I'||s1.charAt(i)=='E'||s1.charAt(i)=='U'||s1.charAt(i)=='O'){
                while(i<j){//后指针
                    if(s1.charAt(j)=='a'||s1.charAt(j)=='i'||s1.charAt(j)=='e'||s1.charAt(j)=='u'||s1.charAt(j)=='o'||s1.charAt(j)=='A'||s1.charAt(j)=='I'||s1.charAt(j)=='E'||s1.charAt(j)=='U'||s1.charAt(j)=='O'){
                        //交换前后两个元音字母
                        t=s1.charAt(i);
                        s1.replace(i,i+1,String.valueOf(s.charAt(j)));
                        s1.replace(j,j+1,String.valueOf(t));
                        j--;
                        break;
                    }
                    j--;
                }
            }
        }
        return s1.toString();//把StringBuffer转换回String,返回
    }
}

  官方答案(双指针):

class Solution {
    public String reverseVowels(String s) {
        int n = s.length();
        char[] arr = s.toCharArray();//把字符串转换成字符数组
        int i = 0, j = n - 1;
        while (i < j) {
            while (i < n && !isVowel(arr[i])) {//不是元音字母就自增,继续找
                ++i;
            }
            while (j > 0 && !isVowel(arr[j])) {//不是元音字母就自减,继续找
                --j;
            }
            //两个指针用同等级的前后顺序,或者用内外层循环也可以
            if (i < j) {
                swap(arr, i, j);
                ++i;
                --j;
            }
        }
        return new String(arr);//把字符数组转换成字符串返回
    }

    public boolean isVowel(char ch) {//判断是否是元音字母
        return "aeiouAEIOU".indexOf(ch) >= 0;//返回字符串"aeiouAEIOU"中字符ch的下标
    }

    public void swap(char[] arr, int i, int j) {//交换方法
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

第七题

    我的答案: 

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int sum=0,len=0;
        for(int i=0;i<nums.length-1;i++){
            if(nums[i]>=target){
                return 1;
            }else{
                sum=nums[i];
                for(int j=i+1;j<nums.length;j++){
                    if(nums[j]>=target){
                        return 1;
                    }else{
                        sum+=nums[j];
                        if(sum>=target){
                            if(len==0){
                                len=j-i+1;
                            }else{
                                len=Math.min(len,j-i+1);
                                break;
                            }
                        }
                    }
                }
            }
        }
        return len;
    }
}

 官方答案:

法一:暴力法

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int ans = Integer.MAX_VALUE;//找最大值,方便参与下面的取最小值函数
        for (int i = 0; i < n; i++) {
            int sum = 0;
            for (int j = i; j < n; j++) {
                sum += nums[j];
                if (sum >= s) {
                    ans = Math.min(ans, j - i + 1);
                    break;
                }
            }
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;//如果ans == Integer.MAX_VALUE,证明没找到符合要求的子数组,返回0
    }
}

 法二:前缀和+二分查找

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int ans = Integer.MAX_VALUE;
        int[] sums = new int[n + 1]; 
        // 为了方便计算,令 size = n + 1 
        // sums[0] = 0 意味着前 0 个元素的前缀和为 0
        // sums[1] = A[0] 前 1 个元素的前缀和为 A[0]
        // 以此类推
        for (int i = 1; i <= n; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        for (int i = 1; i <= n; i++) {
            int target = s + sums[i - 1];
            int bound = Arrays.binarySearch(sums, target);
            if (bound < 0) {
                bound = -bound - 1;
            }
            if (bound <= n) {
                ans = Math.min(ans, bound - (i - 1));
            }
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }
}

  法二:滑动窗口(降低了时间复杂度

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int ans = Integer.MAX_VALUE;
        int start = 0, end = 0;//双指针
        int sum = 0;
        while (end < n) {
            sum += nums[end];
            while (sum >= s) {
                ans = Math.min(ans, end - start + 1);
                sum -= nums[start];//减去了最前面的那个,给最后面的那个腾位置,就像用两块砖头走路一样
                start++;//指针后移
            }
            end++;
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

平安大视野前瞻2023投资策略:资产格局“危中有机”,关注科技、绿色、安全领域

3月3日&#xff0c;平安私人银行全新云端沙龙《平安大视野》第一站在杭州举办&#xff0c;活动聚焦2023年宏观经济展望&#xff0c;邀请中国首席经济学家论坛理事、鹏扬基金首席经济学家陈洪斌&#xff0c;平安私人银行首席策略分析师彭伟伟就国内外宏观经济变化和资产配置策略…

干货系列:高通量测序后的下游实验验证方法——m6A RNA甲基化篇|易基因

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。此前&#xff0c;我们分享了m6A RNA甲基化研究的数据挖掘思路&#xff08;点击查看详情&#xff09;&#xff0c;进而筛选出m6A修饰目标基因。做完MeRIP-seq测序后&#xff0c;如果需要对分…

【JavaWeb】Servlet详解

文章目录1. 前置知识2.servlet生命周期2.1 默认情况下&#xff0c;服务器启动时&#xff0c;servlet对象并没有被创建2.2 用户执行一次请求2.3用户执行第二次请求2.4 3,4,5,6....次请求2.5 关闭服务器3.servlet方法解析4.适配器模式改造servlet4.1不使用servlet模式4.2使用适配…

【微服务】(十五)—— Seata 的部署和集成

文章目录1. 部署Seata的tc-server1.1 下载Seata1.2 解压1.3 修改配置1.4 在nacos添加配置1.5 创建数据库表1.6 启动TC服务2. 微服务集成seata2.1 引入依赖2.2 修改配置文件3. TC服务的高可用和异地容灾3.1 模拟异地容灾的TC集群3.2 将事务组映射配置到nacos3.3 微服务读取nacos…

软测入门(八)Selenium项目实战

自动化项目实战 项目计划设计 测试计划测试范围设定目标规划活动 实际项目中&#xff0c;需要根据项目的实际情况创建自己的项目计划&#xff0c;没有固定的格式和内容要求&#xff1a; 项目简介自动化实现网上购票项目启动前置条件1.购票网站工作正常 2.自动化测试环境准备…

JAVA的16 个实用代码优化小技巧

一、类成员与方法的可见性最小化 举例&#xff1a;如果是一个private的方法&#xff0c;想删除就删除。 如果一个public的service方法&#xff0c;或者一个public的成员变量&#xff0c;删除一下&#xff0c;不得思考很多。 二、使用位移操作替代乘除法 计算机是使用二进制…

垒骰子(爆搜/DP)

动态规划方格取数垒骰子方格取数 题目描述 设有 NNN \times NNN 的方格图 (N≤9)(N \le 9)(N≤9)&#xff0c;我们将其中的某些方格中填入正整数&#xff0c;而其他的方格中则放入数字 000。如下图所示&#xff08;见样例&#xff09;: A0 0 0 0 0 0 0 00 0 13 0 …

ChatGPT助力校招----面试问题分享(一)

1 ChatGPT每日一题&#xff1a;期望薪资是多少 问题&#xff1a;面试官问期望薪资是多少&#xff0c;如何回答 ChatGPT&#xff1a;当面试官问及期望薪资时&#xff0c;以下是一些建议的回答方法&#xff1a; 1、调查市场行情&#xff1a;在回答之前&#xff0c;可以先调查一…

Python基础之while循环

一&#xff1a;while语法 while 条件:代码1 代码2 代码3....while的运行步骤&#xff1a; 步骤1&#xff1a;如果条件为真&#xff0c;那么依次执行&#xff1a;代码1、代码2、代码3、...... 步骤2&#xff1a;执行完毕后再次判断条件,如果条件为True则再次执行&#…

通用缓存存储设计实践

目录介绍 01.整体概述说明 1.1 项目背景介绍1.2 遇到问题记录1.3 基础概念介绍1.4 设计目标1.5 产生收益分析 02.市面存储方案 2.1 缓存存储有哪些2.2 缓存策略有哪些2.3 常见存储方案2.4 市面存储方案说明2.5 存储方案的不足 03.存储方案原理 3.1 Sp存储原理分析3.2 MMKV存储…

【数据挖掘】4、关联分析:Apriori、FP-Growth 算法、买面包是否也爱买啤酒

文章目录一、概念1.1 支持度1.2 置信度1.3 提升度二、Apriori 算法2.1 频繁项集的定义2.2 算法工作原理三、FP-Growth 算法3.1 算法步骤3.1.1 创建项头表3.1.2 构造 FP 树3.1.3 通过 FP 树挖掘频繁项集3.2 手动推导3.2.1 计算单一项的频率&#xff08;支持度计数&#xff09;3.…

shusheng007编程手记

[版权申明] 非商业目的注明出处可自由转载 出自&#xff1a;shusheng007 文章目录概述工具篇IntelliJ IDEA在Idea中下载源码时&#xff0c;报无法下载源码PostmanPost请求被识别成Get请求Linux开启关闭防火墙开放端口关闭端口如何修复磁盘Nginx如何使用docker来安装Nginx概述 …

VMware虚拟网络编辑桥接/NAT/仅主机模式详解

VMware虚拟网络编辑 安装VMware后 默认虚拟网络设置&#xff1a; VMnet0&#xff1a;桥接模式 VMnet1&#xff1a;仅主机 VMnet8&#xff1a;NAT模式 可以打开VMware的虚拟网络适配器查看 NAT模式 NAT模式借助虚拟NAT设备和虚拟DHCP服务器&#xff0c;使得虚拟机可以联网…

掌握Swagger3自动化生成接口文档完成后端提效

文章目录OpenApi规范Swagger3快速上手Swagger3使用Swagger3.x常用注解讲解和配置Api 模块配置ApiOperation 接口配置ApiParam 方法参数配置ApiIgnore 忽略此接口ApiModel()和ApiModelProperty()ApiResponse描述接口响应注意可能出现的问题OpenApi规范 开放API规范&#xff08;…

Java内存屏障简介

简介 内存屏障是插入两个CPU命令之间的命令&#xff0c;禁止处理器命令的重新排序(如屏障)&#xff0c;以确保有序性。此外&#xff0c;为了达到屏障的效果&#xff0c;在处理器写入、读取值之前&#xff0c;将主机的值写入缓存&#xff0c;清空无效的队列&#xff0c;保障可见…

C++函数重载及其背后的原理

写在前面 先说说我的状态吧&#xff0c;五一假期五天假&#xff0c;这些天都在玩&#xff0c;很少学习&#xff0c;我不是后悔&#xff0c;也没必要&#xff0c;本来假期就是为了让自己放松.我唯一要反思看到别人在学,我心里也想学但是却做不到,这是我的缺点,后面我会克服的.尽…

运维提质增效,有哪些办法可以做

凡是代码&#xff0c;难免有 bug。 开发者们的日常&#xff0c;除了用一行行代码搭产品外&#xff0c;便是找出代码里的虫&#xff0c;俗称 debug。 随着移动互联网的快速发展&#xff0c;App 已经成为日常生活中不可或缺的一部分。但是在开发者/运维人员的眼里简直就是痛苦的…

使用R语言包clusterProfiler做KEGG富集分析时出现的错误及解决方法

使用enrichKEGG做通路富集分析时&#xff0c;一直报错&#xff1a;显示No gene can be mapped....k <- enrichKEGG(gene gene, organism "hsa", pvalueCutoff 1, qvalueCutoff 1)但是之前用同样的基因做分析是能够成功地富集到通路&#xff0c;即便是网上的数据…

Appium+Python连接真机、跳过登录页、Unexpected error while obtaining UI hierarchy问题

Appium连接真机 使用数据线连接电脑&#xff0c;然后选择文件传输方式 打开手机设置拉至底部&#xff0c;点击关于手机&#xff0c;连续点击7次版本号打开开发者模式 点击设置中的系统与更新&#xff0c;找到开发者选项----> 打开USB调试即可 在终端中输入adb devices确定…

c语言经典例题-数组的使用

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 选择法排序&#xff1a; 题目&#xff1a; 本关任务&#xff1a;使用选择法排序&#xff08;http://t.csdn.cn/…