java知识和练习
更多java基础知识点击这里:https://zhuanlan.zhihu.com/p/64147696
有 n 个字符串,每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字。这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零。现在问你怎样映射字符才能使得这些字符串表示的整数之和最大?
import java.util.Arrays; import java.util.Comparator; import java.util.Scanner; /** * ABC=100×A+10×B+C * BCA=100×B+10×C+A * ABC+BCA=110×B+101×A+11×C * 要使和最大,则权值越大的映射的数字应越大 */ public class Main { static class Element { long w;//权值 boolean flag;//不能为0 } public static void main(String[] args) { Scanner scan = new Scanner(System.in); while (scan.hasNext()) { int n; Element[] es = new Element[10]; for (int i = 0; i < 10; i++) { es[i] = new Element(); } n = scan.nextInt(); for (int i = 0; i < n; i++) { String str = scan.next(); calWeight(es, str); } System.out.println(sovle(es)); } scan.close(); } private static long sovle(Element[] es) { long res = 0; Arrays.sort(es, new Comparator<Element>() { @Override public int compare(Element e1, Element e2) { return e1.w > e2.w ? 1 : (e1.w == e2.w ? 0 : -1); } }); //权值最低且不能为0 if (es[0].flag) { int i; //权值最小可以为0字母 for (i = 1; i < 10; i++) { if (!es[i].flag) { break; } } Element temp = es[i]; for (; i > 0; i--) { es[i] = es[i - 1]; } es[0] = temp; } for (int i = 9; i >= 0; i--) { res += es[i].w * i; } return res; } private static void calWeight(Element[] es, String str) { int len = str.length(); long base = 1; for (int i = len - 1; i >= 0; i--, base *= 10) { int index = str.charAt(i) - 'A'; es[index].w += base; if (i == 0) {//首字母不能为0 es[index].flag = true; } } } }
有一个由很多木棒构成的集合,每个木棒有对应的长度,请问能否用集合中的这些木棒以某个顺序首尾相连构成一个面积大于 0 的简单多边形且所有木棒都要用上,简单多边形即不会自交的多边形。
初始集合是空的,有两种操作,要么给集合添加一个长度为 L 的木棒,要么删去集合中已经有的某个木棒。每次操作结束后你都需要告知是否能用集合中的这些木棒构成一个简单多边形。
输入描述:
每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n 表示操作的数量(1 ≤ n ≤ 50000) , 接下来有n行,每行第一个整数为操作类型 i (i ∈ {1,2}),第二个整数为一个长度 L(1 ≤ L ≤ 1,000,000,000)。如果 i=1 代表在集合内插入一个长度为 L 的木棒,如果 i=2 代表删去在集合内的一根长度为 L 的木棒。输入数据保证删除时集合中必定存在长度为 L 的木棒,且任意操作后集合都是非空的。
输出描述:
对于每一次操作结束有一次输出,如果集合内的木棒可以构成简单多边形,输出 "Yes" ,否则输出 "No"。
输入
5 1 1 1 1 1 1 2 1 1 2
输出
No No Yes No No
import java.security.PublicKey; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); sc.nextLine(); int num = 0; int j = 0; int max = 0; List<Integer> list = new ArrayList<>(); while (j++ < n) { int i = sc.nextInt(); int l = sc.nextInt(); sc.nextLine(); if (i == 1) { list.add(l); num += l; } else { list.remove(list.indexOf(l)); num -= l; } Collections.sort(list); if(list.size() > 0){ max = list.get(list.size()-1); } if (num - max <= max) { System.out.println("No"); } else { System.out.println("Yes"); } } } }
给出 n 个字符串,对于每个 n 个排列 p,按排列给出的顺序(p[0] , p[1] … p[n-1])依次连接这 n 个字符串都能得到一个长度为这些字符串长度之和的字符串。所以按照这个方法一共可以生成 n! 个字符串。
一个字符串的权值等于把这个字符串循环左移 i 次后得到的字符串仍和原字符串全等的数量,i 的取值为 [1 , 字符串长度]。求这些字符串最后生成的 n! 个字符串中权值为 K 的有多少个。
注:定义把一个串循环左移 1 次等价于把这个串的第一个字符移动到最后一个字符的后面。
递归生成全排列,判断权值,也就是串能分出多少个相同的子串,用KMP可解, 判断n-next[n]能否整除n,可以知道串是否由多个相同字串组成, 除完的商就是权值,不能整除的串权值为1. import java.util.*; public class Main{ static ArrayList<String> res; public static int next(String arr){ int[] next=new int[arr.length()+1]; int res=1; next[0]=next[1]=0; int j=0; for(int i=1;i<arr.length();i++){ while(j>0&&arr.charAt(i)!=arr.charAt(j)) j=next[j]; if(arr.charAt(i)==arr.charAt(j)) { j++; } next[i+1]=j; } if(arr.length()%(arr.length()-next[arr.length()])==0) res=arr.length()/(arr.length()-next[arr.length()]); return res; } public static void allString(String[] strr,int s,int n){ String tmp; if(s==(n-1)){ tmp=""; for(int i=0;i<n;i++){ tmp+=strr[i]; } res.add(tmp); } for(int i=s;i<n;i++){ tmp=strr[s]; strr[s]=strr[i]; strr[i]=tmp; allString(strr,s+1,n); tmp=strr[s]; strr[s]=strr[i]; strr[i]=tmp; } } public static void main(String[] args){ Scanner sc=new Scanner(System.in); int n,k,count; String[] strr; while(sc.hasNext()){ res=new ArrayList<String>(); count=0; n=sc.nextInt(); k=sc.nextInt(); strr=new String[n]; for(int i=0;i<n;i++){ strr[i]=sc.next(); } allString(strr,0,n); for(int i=0;i<res.size();i++){ if(next(res.get(i))==k) count++; } System.out.println(count); } sc.close(); } }
为了不断优化推荐效果,今日头条每天要存储和处理海量数据。假设有这样一种场景:我们对用户按照它们的注册时间先后来标号,对于一类文章,每个用户都有不同的喜好值,我们会想知道某一段时间内注册的用户(标号相连的一批用户)中,有多少用户对这类文章喜好值为k。因为一些特殊的原因,不会出现一个查询的用户区间完全覆盖另一个查询的用户区间(不存在L1<=L2<=R2<=R1)。
输入描述:
输入: 第1行为n代表用户的个数 第2行为n个整数,第i个代表用户标号为i的用户对某类文章的喜好度 第3行为一个正整数q代表查询的组数 第4行到第(3+q)行,每行包含3个整数l,r,k代表一组查询,
即标号为l<=i<=r的用户中对这类文章喜好值为k的用户的个数。 数据范围n <= 300000,q<=300000 k是整型
输出描述:
输出:一共q行,每行一个整数代表喜好值为k的用户的个数
输入例子1:
5 1 2 3 3 5 3 1 2 1 2 4 5 3 5 3
输出例子1:
1 0 2
例子说明1:
样例解释: 有5个用户,喜好值为分别为1、2、3、3、5, 第一组询问对于标号[1,2]的用户喜好值为1的用户的个数是1 第二组询问对于标号[2,4]的用户喜好值为5的用户的个数是0 第三组询问对于标号[3,5]的用户喜好值为3的用户的个数是2
import java.util.*; public class UsrFav { public static void main (String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); HashMap<Integer, List<Integer>> hs = new HashMap<>(); for (int i=0; i < n; i++) { List<Integer> list = new ArrayList<>(); int tmp = sc.nextInt(); if (hs.get(tmp)!= null){ list = hs.get(tmp); } list.add(i+1); hs.put(tmp, list); } int gs = sc.nextInt(); for (int i=0; i < gs; i++){ int lf = sc.nextInt(); int rt = sc.nextInt(); int fav = sc.nextInt(); if (hs.get(fav) == null) { System.out.println(0); continue; } List<Integer> ls = hs.get(fav); int count = 0; //有序链表,此处可以先使用折半查找找到起始位置优化 for (int j=0; j < ls.size(); j++) { if (ls.get(j) > rt) break; if (ls.get(j) < lf) continue; count++; } System.out.println(count); } } }
作为一个手串艺人,有金主向你订购了一条包含n个杂色串珠的手串——每个串珠要么无色,要么涂了若干种颜色。为了使手串的色彩看起来不那么单调,金主要求,手串上的任意一种颜色(不包含无色),在任意连续的m个串珠里至多出现一次(注意这里手串是一个环形)。手串上的颜色一共有c种。现在按顺时针序告诉你n个串珠的手串上,每个串珠用所包含的颜色分别有哪些。请你判断该手串上有多少种颜色不符合要求。即询问有多少种颜色在任意连续m个串珠中出现了至少两次。
输入描述:
第一行输入n,m,c三个数,用空格隔开。(1 <= n <= 10000, 1 <= m <= 1000, 1 <= c <= 50) 接下来n行每行的第一个数num_i(0 <= num_i <= c)表示第i颗珠子有多少种颜色。
接下来依次读入num_i个数字,每个数字x表示第i颗柱子上包含第x种颜色(1 <= x <= c)
输出描述:
一个非负整数,表示该手链上有多少种颜色不符需求。
输入例子1:
5 2 3 3 1 2 3 0 2 2 3 1 2 1 3
输出例子1:
2
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int c = sc.nextInt(); byte[][] matrix = new byte[n][c]; for (int i=0; i<n; i++) { int total = sc.nextInt(); for (int j=0; j<total; j++) { int k = sc.nextInt(); matrix[i][k-1] = 1; } } byte[] result = new byte[c]; for (int i=0; i<c; i++) { int lastIndex = -1; int end = n+m-1; //System.out.println("end is:" + end); for (int j=0; j<end; j++) { int row = j%n; if(matrix[row][i]==1) { if (lastIndex==-1) lastIndex = j; else { if (j-lastIndex < m) result[i] = 1; else { lastIndex = j; } } } } } int sum = 0; for (int i=0; i<c; i++) { if (result[i] ==1) sum++; } System.out.println(sum); } }
方式二
思想:比较通俗易懂,统计每一个颜色出现的位置,使用数据结构Map<颜色,LinkedList颜色的位置>
然后统计每一种颜色是否出错,如果出错,就break,error+1,
importjava.util.HashMap; importjava.util.LinkedList; importjava.util.Map; importjava.util.Scanner; publicclassMain { publicstaticvoidmain(String[] args) { Scanner scanner = newScanner(System.in); intn = scanner.nextInt();// n个手串 intm = scanner.nextInt();// 间隔为m intc = scanner.nextInt();// 有c种颜色 Map<Integer, LinkedList<Integer>> map = newHashMap<Integer, LinkedList<Integer>>(); for(inti = 1; i <= c; i++) { map.put(i, newLinkedList<Integer>()); } inttotal = 1; while(total <= n) { intnum = scanner.nextInt();// 表示有多少顔色 for(inti = 0; i < num; i++) { intcolor = scanner.nextInt(); LinkedList<Integer> linkedList = map.get(color);// 得到某種顔色的位置 linkedList.add(total);// 再加上此位置 map.put(color, linkedList); } total++; } interror = 0; for(inti = 1; i <= c; i++) { LinkedList<Integer> linkedList = map.get(i);// 得到某種顔色的位置 int[] array = newint[linkedList.size()]; intk = 0; for(intj : linkedList) { array[k++] = j; } for(intj = 0; j < array.length; j++) { if(j + 1< array.length && array[j + 1] - array[j] < m) { error++; break; } elseif(j + 1== array.length && array[0] + n - array[j] < m) { error++; break; } } } System.out.println(error); } }
【编码题】字符串S由小写字母构成,长度为n。定义一种操作,每次都可以挑选字符串中任意的两个相邻字母进行交换。询问在至多交换m次之后,字符串中最多有多少个连续的位置上的字母相同?
输入描述:
第一行为一个字符串S与一个非负整数m。(1 <= |S| <= 1000, 1 <= m <= 1000000)
输出描述:
一个非负整数,表示操作之后,连续最长的相同字母数量。
输入例子1:
abcbaa 2
输出例子1:
2
import java.util.*; public class CharMax { public static void main (String[] args) { HashMap<Character, ArrayList<Integer>> hs = new HashMap<>(); int max = 0;//最大连续数 Scanner sc = new Scanner(System.in); String[] arr = sc.nextLine().split("\\s+"); String str = arr[0]; int steps = Integer.parseInt(arr[1]);//总步长 //准备工作 for(int i=0; i < str.length(); i++){ char c = str.charAt(i); ArrayList<Integer> ls = new ArrayList<>(); if (hs.get(c) != null){ ls = hs.get(c); } ls.add(i); hs.put(c, ls); } //开始计算 for (char key : hs.keySet()){ ArrayList<Integer> ls = hs.get(key); int len = ls.size(); if (len <= max) continue; if (len == 1){ max = 1; continue; } for (int i=0; i < ls.size()-1; i++){ int total = 1;//统计连续数 int rest = steps;//可走步长数 int l = i;//左边界 int r = i;//右边界 while( l > 0 || r < ls.size()-1){ //左右边界距离下一个有效值计算 int l_len = Integer.MAX_VALUE;//左边距 int r_len = Integer.MAX_VALUE;//右边距 if (l > 0){ l_len = (ls.get(i) - (i-l)) - ls.get(l-1) - 1; } if (r < ls.size()-1){ r_len = ls.get(r+1) - (ls.get(i) + (r-i)) - 1; } if (l_len < r_len){//左边距 < 右边距 rest -= l_len; if (rest < 0) break; l--;//边界变更 total++; }else{ rest -= r_len; if (rest < 0) break; r++; total++; } } if (total > max) max = total; } } System.out.println(max); } }
方式二
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.next(); int m = sc.nextInt(); Map<Character, List> map = new HashMap<>(26); // key为字符串中的每个字母,value记录该字母在字符串中出现的位置 for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); List list = map.get(c); if (list == null) map.put(c, list = new ArrayList<Integer>(100)); list.add(i); } int maxLen = 1; // 记录连续最长的相同字母数量 // 遍历map for (Map.Entry<Character, List> entry : map.entrySet()) { List<Integer> arrayList = entry.getValue(); // 遍历字母在字符串中出现的位置 for (int i = 0; i < arrayList.size(); i++) { int ctr = arrayList.get(i); // 以当前遍历的元素位置为中心,计算其他相同元素到到该中心需移动的步数 int[] move = new int[arrayList.size()]; // 获取 move[],表示每个相同字母到中心点 ctr 需要移动的最少步数 for (int j = 0; j < arrayList.size(); j++) move[j] = (Math.abs(arrayList.get(j) - ctr) - Math.abs(i - j)); // 排序后,选择移动代价最少的前 k + 1 个 Arrays.sort(move); int sum = 0; // 记录移动步数之和 for (int k = 0; k < move.length; k++) { sum += move[k]; if (sum > m) break; // 每有一个字母移动到中心点,该字母的连续相同数量就增加1 if (k + 1 > maxLen) maxLen = k + 1; } } } System.out.println(maxLen); } }
输入描述:
第一行包括一个数字N,表示本次用例包括多少个待校验的字符串。
后面跟随N行,每行为一个待校验的字符串。
输出描述:
N行,每行包括一个被修复后的字符串。
输入例子1:
2 helloo wooooooow
输出例子1:
hello woow
import java.util.*; public class Main{ public static void main(String []args) { Scanner scanner = new Scanner(System.in); int line = scanner.nextInt(); scanner.nextLine(); for (int i = 0; i < line; i++) { System.out.println(scanner.nextLine().replaceAll("(.)\\1+","$1$1").replaceAll("(.)\\1(.)\\2","$1$1$2")); } } }
输入描述:
第一行包含空格分隔的两个数字 N和D(1 ≤ N ≤ 1000000; 1 ≤ D ≤ 1000000)
第二行包含N个建筑物的的位置,每个位置用一个整数(取值区间为[0, 1000000])表示,从小到大排列(将字节跳动大街看做一条数轴)
输出描述:
一个数字,表示不同埋伏方案的数量。结果可能溢出,请对 99997867 取模
输入
4 3 1 2 3 4
输出
4
说明
可选方案 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)
输入
5 19 1 10 20 30 50
输出
1
说明
可选方案 (1, 10, 20)
//很多人说复杂度会比较高,认为内层循环需要要二叉查找降低复杂度,这个思路确实可行。 但是实际上,对于第二层以j为下标的循环,我们完全不需要每次都从j=i+2进行循环,可以单独用变量right存放上次循环的结果,下一次循环直接从j=right开始就可以了。 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while(in.hasNext()){ int N=in.nextInt(); int D=in.nextInt(); int [] location =new int [N]; for(int i=0 ;i<N;i++){ location[i]=in.nextInt(); } long count =0L; int right=2; for(int i=0;i<N-2;i++){ long temp=0L; for(int j=right;j<N;j++) { if(location[j]-location[i]>D) { break; }else { temp=(long)(j-i); right=j; } } if(temp>=2) count+=temp*(temp-1)/2%99997867; } System.out.println(count%99997867); } } }
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); for(int i = 0; i < N; ++i){ HashMap<String, Integer> mem = new HashMap<>(); HashMap<String, Integer> temp_mem = new HashMap<>(); int M = sc.nextInt(); int max = 1; for(int j = 0; j < M; ++j){ temp_mem.clear(); int n = sc.nextInt(); for(int k = 0; k < n; ++k){ int x = sc.nextInt(); int y = sc.nextInt(); String key = String.valueOf(x) + " " + String.valueOf(y); temp_mem.put(key, mem.getOrDefault(key, 0) + 1); max = Math.max(temp_mem.get(key), max); } mem.clear(); mem.putAll(temp_mem); } if(max <= 1){ System.out.println(1); }else{ System.out.println(max); } } } }

浙公网安备 33010602011771号