以下仅为个人刷题笔记记录,如有错误,敬请指正,勿喷。
数组部分刷题记录
一、数组的遍历(最大连续1 的个数)
question:485
给定一个二进制数组 nums , 计算其中最大连续 1 的个数。
示例1:
输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例二:
输入:nums = [1,0,1,1,0,1]
输出:2
answer:
设置一个temp变量统计当前连续1的个数。当遇到0时,比较当前1的个数 与之前最大值。
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int len=nums.length;
int max=0;
if(len<1){
return max;}
int temp=0;
for(int i=0;i<len;i++){
if(nums[i]==1){
temp+=1;
}else{
max=Math.max(max,temp);
temp=0;
}
}
max=Math.max(max,temp);
return max;
}
}
question:495(提莫攻击)
answer:
用ans记录总秒数,expired记录每次攻击结束的时间。
class Solution {
public int findPoisonedDuration(int[] timeSeries, int duration) {
int ans = 0;
int expired = 0;
for (int i = 0; i < timeSeries.length; ++i) {
//如果当前处于未中毒状态,持续中毒时间加duration;
if (timeSeries[i] >= expired) {
ans += duration;
} else {
//如果当前处于中毒状态,增加的持续时间为 timeSeries[i] + duration - expired;
//timeSeries[i] + duration - expired 为当前timeSeries[i]增加的持续中毒时间
ans += timeSeries[i] + duration - expired;
}
expired = timeSeries[i] + duration;
}
return ans;
}
}
question 414(第三大的数)
answer:
对数组排序,再反转,即递减排序
再找到第三大的数字
用tag作为第几个数的标记标记字段
class Solution {
public int thirdMax(int[] nums) {
//对nums排序
Arrays.sort(nums);
reverse(nums);
for(int i=1,tag=1;i<nums.length;i++){
if(nums[i]!=nums[i-1]&& ++tag==3){
return nums[i];
}
}
return nums[0];
}
public void reverse(int[] nums){
int left=0;
int right=nums.length-1;
while(left<right){
int tem=nums[left];
nums[left]=nums[right];
nums[right]=tem;
left++;
right--;
}
}
}
answer2:
//力扣题解
class Solution {
public int thirdMax(int[] nums) {
//TreeSet表示递增的有序数组
TreeSet<Integer> s = new TreeSet<Integer>();
for (int num : nums) {
s.add(num);
if (s.size() > 3) {
s.remove(s.first());
}
}
return s.size() == 3 ? s.first() : s.last();
}
}
question 628(三个数的最大乘积)
answer:
如果都是正整数:最大乘积为三个最大正整数
如果都是负整数:三大最大负整数
如果正负都有
负数<2 取整数
负数>2 :最小的两个负数*最大正数 or 三个最大正数
综上 找 3个最大的 or 2最小和1个最大;
在这里插入代码片
class Solution {
public int maximumProduct(int[] nums) {
int max1=Integer.MIN_VALUE,max2=Integer.MIN_VALUE,max3=Integer.MIN_VALUE;
int min1=Integer.MAX_VALUE,min2=Integer.MAX_VALUE;
for(int num:nums){
//先找小的
if(num<min1){
min2=min1;
min1=num;
}else if(num<min2){
min2=num;
}
//找大的
if(num>max1){
max3=max2;
max2=max1;
max1=num;
}else if(num>max2){
max3=max2;
max2=num;
}else if(num>max3){
max3=num;
}
}
return Math.max(max1*max2*max3,min1*min2*max1);
}
}
二、统计数组中的元素
question 645(错误的集合)
answer:
用Hash表,将所有的元素,以及其出现的次数 存入hash表中,再判断每一个数字出现的次数
class Solution {
public int[] findErrorNums(int[] nums) {
int len=nums.length;
int[] arr=new int[2];
Map<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
}
for(int i=1;i<=len;i++){
int count=map.getOrDefault(i,0);
if(count==2){
arr[0]=i;
}else if(count==0){
arr[1]=i;
}
}
return arr;
}
}
question 697(数组的度)
answer:
该题是求,出现次数最多的数字中,求其下标距离最近的一组。
所以考虑从数组中的数字出现的次数,第一次出现的下表,和最后一次出现的下表 入手
使用哈希表实现该功能,每一个数映射到一个长度为 3 的数组,数组中的三个元素分别代表这个数出现的次数、这个数在原数组中第一次出现的位置和这个数在原数组中最后一次出现的位置
class Solution {
public int findShortestSubArray(int[] nums) {
int len=nums.length;
Map<Integer,int[]> map=new HashMap<Integer,int[]>();
for(int i=0;i<len;i++){
if(map.containsKey(nums[i])){
map.get(nums[i])[0]++;//数量
map.get(nums[i])[2]=i;//最后一次出现的位置
}else{
map.put(nums[i],new int[]{
1,i,i});//第一次出现
}
}
int maxNum=0,minLen=0;
//对map遍历
for(Map.Entry<Integer,int[]> entry:map.entrySet()){
int[] arr=entry.getValue();
if(maxNum<arr[0]){
maxNum=arr[0];
minLen=arr[2]-arr[1]+1;
}else if(maxNum==arr[0]){
if(minLen>arr[2]-arr[1]+1){
minLen=arr[2]-arr[1]+1;
}
}
}
return minLen;
}
}
question 448(找到所有数组中消失的数字)
这个题,管解思路绝了!!!!
由于nums 的数字范围均在 [1,n]中,我们可以利用这一范围 之外 的数字,来表达「是否存在」的含义。
具体来说,遍历 nums,每遇到一个数 x,就让nums[x−1] 增加 n。由于nums 中所有数均在[1,n]中,增加以后,这些数必然大于 n。最后我们遍历nums,若nums[i] 未大于 n,就说明没有遇到过 数i+1。这样我们就找到了缺失的数字。
注意,当我们遍历到某个位置时,其中的数可能已经被增加过,因此需要对n 取模来还原出它本来的值。