文章目录

  • 相关知识
    • Java中Arrays常用api
  • 相关题目
    • 26.删除有序数组中的重复项
    • 80.删除有序数组中的重复项II
    • 66.加一
    • 75.颜色分类
    • 268.丢失的数字
    • 448.找到所有数组中消失的数字
    • 1403.非递增顺序的最小子序列
    • 1460.通过翻转子数组使两个数组相等
    • 927.三等分

笔者在刷题的过程中,逐渐发现许多题目是基于数组展开的,在数组上进行排序、双指针等一系列操作,对于整个过程的要求非常高。但无奈由于自己之前程序悟性不高,碰上相关题目也是非常棘手,因此想对自己的刷题路径进行整理,方便大家学习。

相关知识

Java中Arrays常用api

Arrays.fill(char[], '.') //将一个数组全填充一样的值
Arrays.equals(int[],int[]) //可以比较两数组是否相同
Arrays.asList(nums[i], nums[j], nums[left], nums[right]) //可以返回List
Arrays.sort(int[],Comparator) //默认升序排列  (a,b)->a-b 小的减去大的  重写Comparator只能针对引用类型 参考解析[如何使用Arrays.sort()](https://blog.csdn.net/Forlogen/article/details/106085173)

相关题目

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

left指向当前不重复数字的最后一个,如果不重复一直往后追加,如果重复则right++忽略,需要明确当且仅当nums[left]==nums[right],应该略过当前的nums[right]。追加的策略是先++left,然后将nums[right]补上,最终还是指向最后一个不重复元素。特别的,由于初始化left为0、right为0,第一个必然重复,因此进行忽略保留nums[left],然后right++,下次交换也是先++left

class Solution {public int removeDuplicates(int[] nums) {int len=nums.length;int left=0;for(int right=0;right<len;right++){if(nums[left]!=nums[right]){//left指向当前不重复数字的最后一个,如果不重复一直往后追加,如果重复则right++忽略,针对第一个位置也有效//应该是++left,先+1再存nums[++left]=nums[right];}}return left+1;}
}

上面是比较nums[left]和nums[right]的大小关系,也可以比较nums[right]、nums[right-1]前后的大小关系。left指向不重复数字最后一个的后一个位置。

class Solution {public int removeDuplicates(int[] nums) {int left=1;int len=nums.length;//比较前后两个值,找到拐点for(int right=1;right<len;right++){if(nums[right]!=nums[right-1]){nums[left]=nums[right];left++;}}return left;}
}

80.删除有序数组中的重复项II

相比于26.删除有序数组中的重复项只能保留一个不重复数字,该题最多能够保存重复数字两次。left定义为满足条件的最后一个元素,需要明确当且仅当nums[left-1]==nums[right],应该略过当前的nums[right],由于有序的特点,这种情况下一定有nums[left-1]==nums[left]==nums[right]。当数字长度小于等于2时,一定可以保留。

也可以参考三叶姐的题解,其中left定义不同。

class Solution {public int removeDuplicates(int[] nums) {int len=nums.length;if(len<=2) return len;int left=1;//left定义为满足要求的最后一个位置for(int right=2;right<len;right++){if(nums[left-1]!=nums[right]){nums[++left]=nums[right];}}//返回数组长度return left+1;}
}

66.加一

个位数加1,只要从低向高考虑到进位就可以。

class Solution {//从末尾开始+1,+1直到没法进位为止,如果全部数位都进位了,需要新构建一个1XXXXX的数组public int[] plusOne(int[] digits) {int len=digits.length;for(int i=len-1;i>=0;i--){digits[i]++;digits[i]%=10;//如果不为0,说明该位没进位,如果为0,则一直往前进位if(digits[i]!=0) return digits;}//如果全部都进位了int[]res=new int[len+1];res[0]=1;return res;}
}

75.颜色分类

由于只有0,1,2这三种数字且知道最后它们的排序顺序,因此只需要统计它们出现的次数,最后组成结果,常数空间但用了两趟扫描。

class Solution {public void sortColors(int[] nums) {int[]fre=new int[3];for(int i:nums){fre[i]++;}for(int i=0;i<fre[0];i++){nums[i]=0;}for(int i=fre[0];i<fre[0]+fre[1];i++){nums[i]=1;}for(int i=fre[0]+fre[1];i<nums.length;i++){nums[i]=2;}}
}

尝试用快排partition的思路加上双指针进行优化,将0推向左边,2推向右边。参考liweiwei大神的题解,需要将区间划分先定义好,算法执行过程中保证“循环不变量”,并且初始化时所有区间都为空

执行过程中,需要根据p0、p1的开闭定义,明白其指向的是最后一个位置,还是最后一个位置的后一个位置(待插入位置)。区间定义为[0,p0)p0指向待插入位置,特别的,执行开始时,也可能会出现自身和自身交换的可能性,自旋以后,p0++指向待插入位置。

class Solution {public void sortColors(int[] nums) {int len=nums.length;//[0,p0)=0//[p0,i)=1//[p2,len)=2     int p0=0;int i=0;int p2=len;//p2已经被包含在后面了,i==p2就能包含所有区间,因此「循环继续」的条件为i<p2while(i<p2){//p0是初始化为0的,因此先交换,再++if(nums[i]==0){swap(nums,i,p0);p0++;i++;}else if(nums[i]==1){i++;}else{//p2是初始化为len的,因此先--,再交换,但是不能保证交换过来的就是1,因此i不变要再判断一次p2--;swap(nums,i,p2);}}}public void swap(int[]nums,int i,int j){int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}
}

268.丢失的数字

本题可以采用多种方法进行求解,参考宫水三叶的题解
原地哈希法:将当前下标i上的数字交换到下标nums[i]上,但是在交换过后需要再次检查当前位置上被交换过来的元素。由于nums中的所有数字都独一无二,因此可以采用这种一对一的做法。

class Solution {public int missingNumber(int[] nums) {int len=nums.length;for(int i=0;i<len;i++){if(nums[i]!=i&&nums[i]<len){//先交换当前位置再--,因为循环出去会+1,又能够检查当前位置swap(nums,nums[i],i--);}}for(int i=0;i<len;i++){if(nums[i]!=i) return i;}//最后的情况肯定是缺nreturn len;}public void swap(int[]nums,int i,int j){int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}
}

异或法:任何数同0异或是其本身,任何数和其本身异或是0。充分考察位运算。

class Solution {public int missingNumber(int[] nums) {int ans=0;int len=nums.length;for(int i=0;i<=len;i++){ans^=i;}for(int i:nums){ans^=i;}return ans;}
}

448.找到所有数组中消失的数字

这题相比于上一题,可能会出现重复的数字,而导致[1,n]范围内有多个数字没出现,并且数据都是正数,采用的方法是进行原地负数标记,即将当前的数字的「绝对值减一」作为下标,将该下标处的数字改为负数,已经改变的就保持负数,最后遍历一次,仍然为正数的「下标加上一」就是未出现的数字。

class Solution {//注意可能会由于重复的数字,多个数字未出现public List<Integer> findDisappearedNumbers(int[] nums) {ArrayList<Integer> ans=new ArrayList<>();for(int i=0;i<nums.length;i++){nums[Math.abs(nums[i])-1]=-Math.abs(nums[Math.abs(nums[i])-1]);}for(int i=0;i<nums.length;i++){if(nums[i]>0) ans.add(i+1);}return ans;}
}

1403.非递增顺序的最小子序列

贪心做法,先降序处理,然后求出达到总和的一半+1需要的最少数字。

由于Arrays.sort()默认只对int[]数组升序排列,如果要降序排列,不能使用基本类型(int, double, char),如果是int型需要改成Integer,float要改成Float,因此我们进行包装以后排序,然后进行处理。

class Solution {public List<Integer> minSubsequence(int[] nums) {int len=nums.length;Integer[] numsI=new Integer[len];for(int i=0;i<len;i++){numsI[i]=new Integer(nums[i]);}Arrays.sort(numsI,(a,b)->b-a);ArrayList<Integer> ans=new ArrayList<>();int sum=0;for(int i:numsI){sum+=i;}//保证大于别的部分int target=sum/2+1;int index=0;while(target>0){target-=numsI[index];ans.add(numsI[index++]);}return ans;}
}

或者先用默认的降序排列,然后进行颠倒:

class Solution {public List<Integer> minSubsequence(int[] nums) {int len=nums.length;Arrays.sort(nums);for(int i=0,j=nums.length-1;i<j;i++,j--){int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}ArrayList<Integer> ans=new ArrayList<>();int sum=0;for(int i:nums){sum+=i;}//保证大于别的部分int target=sum/2+1;int index=0;while(target>0){target-=nums[index];ans.add(nums[index++]);}return ans;}
}

1460.通过翻转子数组使两个数组相等

脑筋急转弯,如果两个数组出现的数字及频率完全相同,那么一定能够通过翻转子数组使得两个数组相等。

class Solution {public boolean canBeEqual(int[] target, int[] arr) {int len=target.length;int[]targeta=new int[1010];int[]arra=new int[1010];for(int i=0;i<len;i++){targeta[target[i]]++;arra[arr[i]]++;}return Arrays.equals(targeta,arra);}
}

927.三等分

将数组中的1三等分,记录每组1的第一个位置;按第三组中1到末尾来确定最终每组的二进制数(前导0不重要,但是后面的1后面的0会影响数字大小)。这样只需要比较从每组1的第一个位置开始,是否和第三组的0,1分布一样就行了。

class Solution:def threeEqualParts(self, arr: List[int]) -> List[int]:one=arr.count(1)if one%3:return [-1,-1]if not one:return [0,len(arr)-1]cnt,a,b,c,each=0,-1,-1,-1,one//3for i,num in enumerate(arr):if num:cnt += 1if a==-1 and cnt:a=iif b==-1 and cnt>each:b=iif c==-1 and cnt>2*each:c=ibreakif (length:=len(arr)-c) and arr[a:a+length]==arr[b:b+length]==arr[c:]:return [a+length-1,b+length]return [-1,-1]

算法学习-数组的相关操作,简单的数据结构逆天的难度,扮猪吃老虎(持续更新中)相关推荐

  1. python ctypes调用C++ dll,arry(数组)的相关操作

    @[TOC](python ctypes调用C++ dll,arry(数组)的相关操作) 前言 本人新手python一枚,最近工作中需要用到python 调用C++库,一个数组调用,花费了太多时间,遂 ...

  2. 本专栏所有力扣题目的目录链接, 刷算法题目的顺序(由易到难/面试频率)/注意点/技巧, 以及思维导图源文件问题(持续更新中)

    这篇文章为本专栏所有力扣题目提供目录链接, 更加方便读者根据题型或面试频率进行阅读, 此外也会介绍我在刷题过程中总结的刷算法题目的顺序/注意点/技巧, 最后说下文中出现的思维导图源文件的问题 和 打卡 ...

  3. php 空二位数组,php对二维数组进行相关操作(排序、转换、去空白等),php二维数组_PHP教程...

    function printr($arr) { echo ''; print_r($arr); echo ' '; } 第一组 :sort 和 rsort,按照PHP数组键值的顺序asc和逆序desc ...

  4. Windows基本命令操作、网络相关操作、windows用户管理、NTFS权限、更新策略的方法

    一.Windows基本命令操作 一.目录与文件应用操作 1.cd 命令 用于改变当前提示符盘符路径或提示符目录路径 CD [/D] [drive:][path] #跨盘符切换必须要跟上 /d 选项 举 ...

  5. Go语言开发学习笔记(持续更新中)

    Go语言开发学习笔记(持续更新中) 仅供自我学习 更好的文档请选择下方 https://studygolang.com/pkgdoc https://www.topgoer.com/go%E5%9F% ...

  6. 嵌入式相关开源项目、库、资料------持续更新中

    学习初期最难找的就是找学习资料了,本贴精心汇总了一些嵌入式相关资源,包括但不限于编程语言.单片机.开源项目.物联网.操作系统.Linux.计算机等资源,并且在不断地更新中,致力于打造全网最全的嵌入式资 ...

  7. 我学习 Java 的历程和体会(写给新手看,欢迎老司机批评和建议,持续更新中)

    我学习 Java 的历程和体会(写给新手看,欢迎老司机批评和建议,持续更新中) 最初写这篇文章的时候,是在今年的 9 月中旬.今天,我想再写写这将近两个多月以来的感受. 在今年的 10 月我来到北京求 ...

  8. C语言学习笔记Day3——持续更新中... ...

    上一篇文章C语言学习笔记Day2--持续更新中- - 八. 容器 1. 一维数组 1.1 什么是一维数组 当数组中每个元素都只带有一个下标(第一个元素的下标为0, 第二个元素的下标为1, 以此类推)时 ...

  9. FRM学习复习2(持续更新中..)

    (此文仅记录学习进程,加油!) FRM学习复习2(持续更新中..) Framework框架 overview of risk management风险管理概述 framework overview R ...

最新文章

  1. Using PyQt first procedure-bupt IPTV client
  2. android 多行 对齐方式,android – 按钮与多行文字下沉对齐线,如何解决?
  3. 华为云服务器自己维护吗,云服务器要维护吗
  4. 浅谈数据仓库建设中的数据建模方法
  5. 内存中发堆和栈,栈是运行时的单位,而堆是存储的单位
  6. php mysql怎么实现,使用php与mysql怎么实现一个无限级分类
  7. win10网卡高级属性配置图解_简单设置,win10再也不会断网了
  8. mysql镜像备份和同步备份_mysql 主从同步及备份
  9. Python根据正则表达式找到相应的字符串然后进行替换
  10. 大数据时代的语音识别,方言也不怕?
  11. NOIP2010-普及组初赛C语言解析
  12. AE弹簧弹球动画表达式
  13. 京东官网(京东注册,京东登录,京东首页,京东购物车,京东详情页,京东列表页)
  14. sensor gyro_3d not found
  15. vue echarts饼状统计
  16. 条款30:透彻了解inlining的里里外外
  17. 2.Deep Crossing: Web-Scale Modeling without Manually Crafted Combinatorial Features论文核心解读以及代码实现
  18. PHP pdo查询sqlite,PHP PDO 操作 sqlite数据库 案例
  19. linux添加了路径还是不能调用_166个最常用的Linux命令,哪些你还不知道?
  20. C语言中和||的用法

热门文章

  1. 数学建模番外篇8:画图配色
  2. java项目的目录结构
  3. 图形学中的贴图采样、走样与反走样等
  4. Linux安装JMeter进行压力测试
  5. 计算机组装与维修 字长,计算机组装与维修知识点总结.doc
  6. uniapp中实现微信H5定位、解决跨域问题
  7. (附源码)计算机毕业设计Java房产中介管理系统
  8. 如何查看PDF的坐标
  9. javaweb:web.xml配置详解
  10. RabbitMQ除开RPC的五种消模型----原生API