1.平均数为k的最长连续子数组【有点难度,主要是这个思路是真没想起来】
题意理解:
求最长连续子序列,该子序列满足平均值为k的条件
解题思路:
1.双for循环遍历所有子串,但是超时了
2.第二种思路, 给所有的元素-平均数k,问题就变成了最长连续子序列,和为0,所以呢?然后相等还是遍历所有子串,和之前没有什么不同了,时间复杂度还是过不去。
3.第三种思路,借鉴大佬的思路,原来考的是前缀和+哈希表
哈希表里面存的值是索引,需要注意累加和sum需要用long
使用pre来记录前n个元素的和,map记录的是截止当前索引i下,元素和为cur
其实本质思路是:
第i个元素的时候求和sum=a, 第j个元素的时候求和sum=a则说明
(i,j]区间的元素和为0,故此处长度为0的子串长度为: j-i
1.解题思路
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Main solution=new Main();Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别int n = in.nextInt();int k = in.nextInt();int[] nums=new int[n];for(int i=0;i<n;i++){nums[i]=in.nextInt();}System.out.println(solution.compute(n,k,nums));}public int compute(int n,int k,int[] nums){//记录结果int maxLen=-1;//前i个数的和long pre=0;Map<Long,Integer> map=new HashMap<>();map.put(0L,0);for(int i=0;i<n;i++){//将avg=k的约束转换为sum=0long cur=pre+nums[i]-k;if(map.containsKey(cur)){maxLen=Math.max(maxLen,i+1-map.get(cur));}else{map.put(cur,i+1);}pre=cur;}return maxLen;}}
2.复杂度分析
时间复杂度:O(n) for循环的存好
空间复杂度: O(2n) map的元素存储损耗
2.小球投盒【不难,但是可能出小问题】
题意理解:
有一堆盒子,两种操作:
操作1:往编号为i的元素中放一个球
操作2:除编号i的元素放一个球
操作到第几次时,所有盒子里都有小球
解题思路:
1.用一个list模拟盒子,进行操作,放过球,则将对应元素n移除list, 当前仅当list为空时,所有盒子有小球
2.考的是控制处理流程,不算难,但是容易超时
几个超时问题:
set.clear()会超时,但是set=new HashSet<>()不会,空间换时间的tips
1.解题
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Main main = new Main();Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();int[][] opts = new int[m][2];for (int i = 0; i < m; i++) {opts[i][0] = in.nextInt();opts[i][1] = in.nextInt();}System.out.println(main.commpute(n, m, opts));}public int commpute(int box, int optNum, int[][] opts) {Set<Integer> set = new HashSet<>();for(int i=1;i<=box;i++) set.add(i);for(int i=1;i<=optNum;i++){int target=opts[i-1][1];//移除一个小球if(opts[i-1][0]==1&&set.contains(target)){set.remove( target);}else if(opts[i-1][0]==2&&(!set.isEmpty())){if(set.contains(target)){set=new HashSet<>();set.add(target);}else{set.clear();}}if(set.isEmpty()){return i;}}return -1;}
}
2.复杂度分析
时间复杂度:O(n) for循环遍历的时间损耗
空间复杂度:O(2n) 盒子的空间损耗+opts操作存储的空间损耗
3.小红结账【简单题】
题意理解:
共有n个账单,每次k个人吃饭,每次给小红的钱向上取整。
其中小红的朋友共m个,其中同一个朋友可能参与多次聚餐,需计算,每个人总共需要转给小红的账单。而不是某一个账单需要转的钱!
解题思路:
题目比较简单。使用payResult[m]维护结果,其中payResult[i]表示n个账单中,第i个朋友需给小红转的钱。
遍历账单,计算avg平均数
将平均数,加至指定朋友需付的钱中
返回结果
1.解题
import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Main solution=new Main();Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();int[][] costItem=new int[n][2];String[] friends=new String[n];for(int i=0;i<n;i++){costItem[i][0]=in.nextInt();costItem[i][1]=in.nextInt();in.nextLine();friends[i]=in.nextLine();}long[] payResult=solution.compute(n,m,costItem,friends);for(long num:payResult){System.out.print(num+" ");}}public long[] compute(int n,int m,int[][] costItem,String[] friends){long[] payResult=new long[m];//遍历账单for(int i=0;i<n;i++){String[] num=friends[i].split(" ");// System.out.println("S:"+friends[i]+" | "+num.length);int payItem=(costItem[i][1]+num.length)/costItem[i][0];// System.out.println("Avg:"+payItem);for(int j=0;j<num.length;j++){int index=Integer.valueOf(num[j])-1;payResult[index]+=payItem;}}return payResult;}
}
2.复杂度分析
时间复杂度:O(O^2) 双for循环时间损耗
空间复杂度:O(2n) 账单存储损耗+结果数组存储损耗
4.小美的游戏【简单题】
题意理解:
有个n个元素的数组,将两个元素的ai,aj的乘积换成x,y的乘积,要使整个数组的总和尽可能的大。
解题思路:
为了使整个数组总和尽可能的大,就要使元素尽可能的大,最有效的一个方式如:
比如获得两个元素: 4*5=20*1 将元素4+5换成20+1,
所以,尽可能让两个大的元素相乘,并将其转换为1*乘积的两个元素,此时和最大
1.对数组排序,大数在数组后面
2.从后面进行遍历,每次将两个最大的数相乘,转换为1*乘积
3.总是把1放在后面(i),乘积常在前面(i-1)的位置,方便继续两个最大值的相乘。
4.最后求和
1.解题
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Main solution=new Main();Scanner in = new Scanner(System.in);int n = in.nextInt();int k = in.nextInt();long[] nums=new long[n];for(int i=0;i<n;i++){nums[i]=in.nextLong();}System.out.println(solution.compute(n,k,nums));}public long compute(int n,int k,long[] nums){long result=0;Arrays.sort(nums);for(int i=nums.length-1;i>=0;i--){if(k>0&&i>0){nums[i-1]=(long)(((nums[i]%(Math.pow(10,9)+7))*(nums[i-1]%(Math.pow(10,9)+7)))%(Math.pow(10,9)+7));nums[i]=1;k--;}result=(long)((result+nums[i])%(Math.pow(10,9)+7));}return result;}
}
2.复杂度分析
时间复杂度:O(n) for循环的时间损耗
空间复杂度:O(n) nums数组的空间损耗
5.小美种果树 【简单题】
题意理解:
一个树成熟需要能量值z
每天浇水+x
每三天施肥+y
求累计几天,能量值到达z
解题思路:
比较简单,在合适的位置累加x,y,当前且仅当sum>=z时,跳出循环,树成熟
1.解题
import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Main solution=new Main();Scanner in = new Scanner(System.in);int x = in.nextInt();int y = in.nextInt();int z = in.nextInt();System.out.println(solution.compute(x,y,z));}public int compute(int x,int y,int z){int sum=0;int i=0;while(sum<z){sum+=x;if(i%3==0){sum+=y;}i++;}return i;}
}
2.复杂度分析
时间复杂度:O(n) while循环的时间损耗
空间复杂度:O(1) 存储result的空间损耗
6.小美的数组重排【简单题】
题意理解:
两个数组,要求元素重排后,对应位置上的元素和满足[1,m]的条件限制
能满足该条件则输出Yes,负责输出No
共进行q次判断(询问)
解题思路:
对于数组a升序排列,数组b降序排列
检查对应位置是否满足值在[1,m]的约束,符合Yes,否则No
1.遍历q次询问
2.判断
3.输出结果
1.解题
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Main main=new Main();Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别int q=in.nextInt();String[] result=new String[q];for(int i=0;i<q;i++){int n=in.nextInt();int m=in.nextInt();int[] a=new int[n];int[] b=new int[n];for(int j=0;j<n;j++){a[j]=in.nextInt();}for(int j=0;j<n;j++){b[j]=in.nextInt();}result[i]=main.compute(n,m,a,b);}for(String s:result){System.out.println(s);}}public String compute(int n,int m,int[] aArr,int[] bArr){Arrays.sort(aArr);Arrays.sort(bArr);for(int i=0;i<n;i++){if(aArr[i]+bArr[n-1-i]>m||aArr[i]+bArr[n-1-i]<1) return "No";}return "Yes";}
}
2.复杂度分析
时间复杂度:O(nlogn) sort的时间损耗
空间复杂度:O(n) 以为数组存储元素的空间损耗
7.判断ip地址是否合法【不难但易错】
题意理解:
对于IP地址的判断
1.是否合法地址
2.是A\B\C哪类地址
解题思路:
题目比较好理解,但容易出错
需要注意的地方:
1. address.split("\\.")
当且仅当.在最后一位时:如1.2.3.4. 划分结果 1 2 3 4,但是其实是非法地址
当且仅当.在第一位时:如 .1.2.3.4 划分结果为 “” 1 2 3 4,非法地址
2.对于地址每部分,1.02.3.4 02是非法的表达
3.对于非. 非数组的部分存在时,也是非法表达
1.解题
import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Main main=new Main();Scanner in = new Scanner(System.in);String address=in.nextLine();boolean flag=true;//元素检查for(int i=0;i<address.length();i++){if(address.charAt(i)!='.'&&(!Character.isDigit(address.charAt(i)))){flag=false;break;}if(address.charAt(i)=='.'&&i==address.length()-1){flag=false;}}//组成检查if(flag==true){String[] parts=address.split("\\.");if(parts.length!=4) flag=false;else{for(String part:parts){if("".equals(part.trim())){flag=false;break;}if(part.length()>=2&&part.startsWith("0")){flag=false;break;}}}}if(flag==false){System.out.println("invalid");}else{System.out.println(main.compute(address));}}public String compute(String addressStr){String result="";String[] address=addressStr.split("\\.");int part1=Integer.valueOf(address[0]);int part2=Integer.valueOf(address[1]);int part3=Integer.valueOf(address[2]);int part4=Integer.valueOf(address[3]);if(part1<0||part1>255||part2<0||part2>255||part3<0||part3>255||part4<0||part4>255) result="invalid";else if(part1<=125&&part1>=1){result="A_address";}else if(part1==126&&part2==0&&part3==0&&part4==0){result="A_address";}else if(part1<=191&&part1>=128){result="B_address";}else if(part1<=223&&part1>=192){result="C_address";}else {result="other";}return result;}
}
2.复杂度分析
时间复杂度:O(n) for循环时间损耗
空间复杂度:O(1) 结果result空间损耗