头条的2017校招开始了!为了这次校招,我们组织了一个规模宏大的出题团队,每个出题人都出了一些有趣的题目,而我们现在想把这些题目组合成若干场考试出来,在选题之前,我们对题目进行了盲审,并定出了每道题的难度系统。一场考试包含3道开放性题目,假设他们的难度从小到大分别为a,b,c,我们希望这3道题能满足下列条件:
a<=b<=c
b-a<=10
c-b<=10
所有出题人一共出了n道开放性题目。现在我们想把这n道题分布到若干场考试中(1场或多场,每道题都必须使用且只能用一次),然而由于上述条件的限制,可能有一些考试没法凑够3道题,因此出题人就需要多出一些适当难度的题目来让每场考试都达到要求,然而我们出题已经出得很累了,你能计算出我们最少还需要再出几道题吗?
输入描述:
输入的第一行包含一个整数n,表示目前已经出好的题目数量。
第二行给出每道题目的难度系数d1,d2,…,dn。
数据范围
对于30%的数据,1 ≤ n,di ≤ 5;
对于100%的数据,1 ≤ n ≤ 10^5,1 ≤ di ≤ 100。
在样例中,一种可行的方案是添加2个难度分别为20和50的题目,这样可以组合成两场考试:(20 20 23)和(35,40,50)。
输出描述:
输出只包括一行,即所求的答案。
输入例子1:
4
20 35 23 40
输出例子1:
2
解析: 思路 第一步:进行排序将输入的难度进行排序处理
第二步: 首先看 a1,a2,a3 ---这三个数进行比较,确定 添加的题目数
FIRST: 如果 a2-a1<=10 && a3-a2<=10 符合要求,从a4,a5,a6下三组进行开始
SECOND:如果 a2-a1>10 && a2-a1<=20 数量+1,跳到第三个从 a3,a4,a5开始
THIRD:如果a2-a1>20 则所在数量+2,从a2,a3,a4 开始
FORTH:如果a2-a1<=10 ,并且 a3-a2>10 则数量+1,a3,a4,a5 下一组开始
1 import java.util.Arrays; 2 import java.util.Scanner; 3 4 /** 5 * Created by Workstation on 2017/8/21. 6 */ 7 public class Main { 8 9 public static void main (String[] args) { 10 test_1 (); 11 12 } 13 14 public static void test_1() 15 { 16 Scanner in=new Scanner (System.in); 17 18 int M=in.nextInt (); 19 int[] arr=new int[M]; 20 for(int i=0;i<M;i++) 21 { 22 arr[i]=in.nextInt ();// 依次将输入的结果进行排序 23 } 24 Arrays.sort (arr); 25 26 //进行处理 27 int count=0,index=0; 28 int n=arr.length; 29 while(index<arr.length) 30 { 31 if((index+1<n) && (index+2)<n && arr[index+1]-arr[index]<=10) 32 { 33 if(arr[index+2]-arr[index+1]<=10)// 属于第一种情形 34 { 35 index+=3; 36 }else // a3-a2>10 37 { 38 count+=1; 39 index+=2;// 从 a2,a3,a4开始 40 } 41 }else if(index+1<n && arr[index+1]-arr[index]<=20) 42 { 43 count+=1; 44 index+=2; 45 }else 46 { 47 count+=2; 48 index+=1; 49 } 50 } 51 if(index==n-1) count+=2; 52 System.out.println(count); 53 } 54 }
给定整数m以及n各数字A1,A2,..An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大于m的有多少个。
输入描述:
第一行包含两个整数n,m. 第二行给出n个整数A1,A2,...,An。 数据范围 对于30%的数据,1 <= n, m <= 1000 对于100%的数据,1 <= n, m, Ai <= 10^5
输出描述:
输出仅包括一行,即所求的答案
示例1
输入
3 10 6 5 10 解析: 引入 概念T:Trie树,单词树,主要用于 字符串的查找和前缀匹配,利用串构建一个字典树,该字典树保留串的公共的前缀西欧爱心,以英文字母为例子: 每一个Trie树 中每一个节点包含26个孩子节点,:
如下给出字符串"abc","ab","bd","dda",根据该字符串序列构建一棵Trie树。则构建的树如下:Trie树根节点不包含任何信息,第一个字符串"abc" 第一个
字母a,因此在根节点数组中找到字符串下标a-97 数组下标的值不为NULL就行,同样依次类推:查找字符串“abc“ 查找的长度olog(Len) ,采用匹配耗时间哦(n*len) 解题:使用Tire树,将n个数字分别装换成二进制形式进行存储到Trie树,比较a[i]元素和m对应二进制每一位的比值:数据最多10^5 对于每一个节点 使用1<< 17 才能够满足哦,因此需要空间10^5*17 byte= 大概是210KB左右的空间; 有用的东西:和1异或相当于该位上的数进行取反,同时a^b=c有 a^c=b: 这一道题:可以摆每一个数的二进制求出来,用一个字典树进行维护,之后遍历每一个数按照位的贪心算法进行:1.如果这一位对应位m是1,那么与此位相异或必须是1,如果这一位m是0,要大于m的话异或的这一位可以是1或者是0,ans加上之前维护过的二进制位加上这一位为1的数在字典树中查询到有多小满足这个前缀的条件,之后让这一位的异或为0,继续往下遍历,最后除以2图如下所示 当前m=0:想大于m这一位相与必须要是1,m=1 只能递归判断下一位
直接计算肯定是超时的,所以这问题不能使用暴力破解,考虑到从高位到地位,依次进行位运算,如果两个数异或结果在某高位为1,而m的对应位为0,则肯定任何这两位异或结果为1的都会比m大。 直接从高到低位进行判断
由此,考虑使用字典树(TrieTree)从高位到第位建立字典,再使用每个元素依次去字典中查对应高位异或为1, 而m为0的数的个数,相加在除以2既是最终的结果;直接贴出代码如下,非原创,欢迎讨论;
补充:queryTrieTree在搜索的过程中,是从高位往低位搜索,那么,如果有一个数与字典中的数异或结果的第k位大于m的第k位,那么该数与对应分支中所有的数异或结果都会大于m, 否则,就要搜索在第k位异或相等的情况下,更低位的异或结果。queryTrieTree中四个分支的作用分别如下: 当mDigi位为1 的时候不得不递归d下一位
1. aDigit=1, mDigit=1时,字典中第k位为0,异或结果为1,需要继续搜索更低位,第k位为1,异或结果为0,小于mDigit,不用理会;
2. aDigit=0, mDigit=1时,字典中第k位为1,异或结果为1,需要继续搜索更低位,第k位为0,异或结果为0,小于mDigit,不用理会;
3. aDigit=1, mDigit=0时,字典中第k位为0,异或结果为1,与对应分支所有数异或,结果都会大于m,第k位为1,异或结果为0,递归获得结果;
4. aDigit=0, mDigit=0时,字典中第k位为1,异或结果为1,与对应分支所有数异或,结果都会大于m,第k位为0,异或结果为0,递归获得结果;
1 import java.util.Scanner; 2 3 public class Main { 4 private static class TrieTree { 5 TrieTree[] next = new TrieTree[2]; 6 int count = 1; 7 } 8 9 public static void main(String[] args) { 10 Scanner sc = new Scanner(System.in); 11 while (sc.hasNext()){ 12 int n = sc.nextInt(); 13 int m = sc.nextInt(); 14 int[] a = new int[n]; 15 for (int i = 0; i < n; i++) { 16 a[i] = sc.nextInt(); 17 } 18 System.out.println(solve(a, m)); 19 } 20 } 21 22 private static long solve(int[] a, int m) { 23 TrieTree trieTree = buildTrieTree(a); 24 long result = 0; 25 for (int i = 0; i < a.length; i++) { 26 result += queryTrieTree(trieTree, a[i], m, 31); 27 } 28 return result / 2; 29 } 30 31 private static long queryTrieTree(TrieTree trieTree, int a, int m, int index) { 32 if(trieTree == null) 33 return 0; 34 35 TrieTree current = trieTree; 36 for (int i = index; i >= 0; i--) { 37 int aDigit = (a >> i) & 1; 38 int mDigit = (m >> i) & 1; 39 if(aDigit == 1 && mDigit == 1) { 40 if(current.next[0] == null) 41 return 0; 42 current = current.next[0]; 43 } else if (aDigit == 0 && mDigit == 1) { 44 if(current.next[1] == null) 45 return 0; 46 current = current.next[1]; 47 } else if (aDigit == 1 && mDigit == 0) { 48 long p = queryTrieTree(current.next[1], a, m, i - 1); 49 long q = current.next[0] == null ? 0 : current.next[0].count; 50 return p + q; 51 } else if (aDigit == 0 && mDigit == 0) { 52 long p = queryTrieTree(current.next[0], a, m, i - 1); 53 long q = current.next[1] == null ? 0 : current.next[1].count; 54 return p + q; 55 } 56 } 57 return 0; 58 } 59 60 private static TrieTree buildTrieTree(int[] a) { 61 TrieTree trieTree = new TrieTree(); 62 for (int i = 0; i < a.length; i++) { 63 TrieTree current = trieTree; 64 for (int j = 31; j >= 0; j--) { 65 int digit = (a[i] >> j) & 1; 66 if(current.next[digit] == null) { 67 current.next[digit] = new TrieTree(); 68 } else { 69 current.next[digit].count ++; 70 } 71 current = current.next[digit]; 72 } 73 } 74 return trieTree; 75 } 76 }
输入 1-n的数字按照字典进行排序
给定整数n和m, 将1到n的这n个整数按字典序排列之后, 求其中的第m个数。
对于n=11, m=4, 按字典序排列依次为1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 因此第4个数是2.
对于n=200, m=25, 按字典序排列依次为1 10 100 101 102 103 104 105 106 107 108 109 11 110 111 112 113 114 115 116 117 118 119 12 120 121 122 123 124 125 126 127 128 129 13 130 131 132 133 134 135 136 137 138 139 14 140 141 142 143 144 145 146 147 148 149 15 150 151 152 153 154 155 156 157 158 159 16 160 161 162 163 164 165 166 167 168 169 17 170 171 172 173 174 175 176 177 178 179 18 180 181 182 183 184 185 186 187 188 189 19 190 191 192 193 194 195 196 197 198 199 2 20 200 21 22 23 24 25 26 27 28 29 3 30 31 32 33 34 35 36 37 38 39 4 40 41 42 43 44 45 46 47 48 49 5 50 51 52 53 54 55 56 57 58 59 6 60 61 62 63 64 65 66 67 68 69 7 70 71 72 73 74 75 76 77 78 79 8 80 81 82 83 84 85 86 87 88 89 9 90 91 92 93 94 95 96 97 98 99 因此第25个数是120…
1 public class Main { 2 // 使用一点小手段计算结果只有80% 的通过,说明这个算法还是可以进行调整 3 public static void main (String[] args) { 4 5 Scanner in=new Scanner (System.in); 6 Long n=in.nextLong (); 7 Long m=in.nextLong (); 8 int cur=1; 9 for(int i=1;i<m;i++) 10 { 11 if(cur*10<=n) 12 { 13 cur*=10;// 进行扩展位 14 }else 15 { 16 if(cur>=n) cur=cur/10;//防止越界 17 cur+=1; 18 while(cur%10==0) cur/=10; 19 } 20 } 21 System.out.println(cur); 22 } 23 24 }
找出函数的最宽尖峰
【题目描述】按数组的形式给出函数f(x)的取值,即数组A的A[0]元素为f(0)的取值,数组的取值都为整数,函数在每个点都是严格单调递增或者严格递减(即A[i-1] != A[i] != A[i+1]),要求找出最宽的先上升后下降的区间(这个区间内函数的值必须先上升到一个点然后下降,区间的上升段和下降段长度必须都大于0)。
1. 如果找到符合条件的最大区间输出数组对应的左右下标(保证只有一个最大区间)
2. 找不到那么输出-1 -1
输入格式
n
n长度的整数数组
输出格式
区间的范围
输入样例
10
1 3 1 2 5 4 3 1 9 10
输出样例
2 7
数据规模
对于 100% 的数据,1 <=n <=10, 000, 000
解析:此题有点类似与排队序列相似
1 public static void test_4() 2 { 3 Scanner in=new Scanner(System.in); 4 int n=in.nextInt (); 5 int [] x=new int[n]; 6 7 for(int i=0;i<n;i++) 8 x[i]=in.nextInt (); 9 10 int [] dpL=new int[n]; 11 12 for(int i=1;i<n;i++) 13 { 14 if(x[i]-x[i-1]>0) 15 { 16 dpL[i]=dpL[i-1]+1; 17 } 18 } 19 20 int [] dpR=new int[n]; 21 22 for(int i=n-2;i>=0;i--) 23 { 24 if(x[i]-x[i+1]>0) 25 { 26 dpR[i]=dpR[i+1]+1; 27 } 28 } 29 30 int mx=0,LL=-1,RR=-1; 31 for(int i=0;i<n;i++) 32 { 33 if(dpL[i]>0 && dpR[i]>0 && dpL[i]+dpR[i]>mx) 34 { 35 mx=dpL[i]+dpR[i]; 36 LL=i-dpL[i]; 37 RR=i+dpR[i]; 38 } 39 } 40 System.out.println(LL+" "+RR); 41 }
Paragraph
【问题描述】给定一个段落,由 N 个句子组成。第 i 个句子的长度为 L[i],包含的单词个数为 W[i]。
句子不包含任何除字母和空格( ) 外的符号。
每个句子内部,含有若干个单词,由空格( ) 分隔。句子不会包含连续的空格。
随后给定 M 个查询,每个查询包含一个句子,需要在段落中寻找相同单词数量最多的句子。重复的单词只计一次,且不区分大小写。
输入数据将保证结果是存在且唯一的。
输入格式
第一行是两个整数 N 和 M。
接下来的 N+M 行,每行包含一个句子。
前 N 行代表段落中的句子,后 M 行表示查询。
输出格式
输出 M 行,每行代表查询的结果。
输入样例
6 3
An algorithm is an effective method that can be expressed within a finite amount of space and time
Starting from an initial state and initial input the instructions describe a computation
That when executed proceeds through a finite number of successive states
Eventually producing output and terminating at a final ending state
The transition from one state to the next is not necessarily deterministic
Some algorithms known as randomized algorithms incorporate random input
Next to the transition
Wormhole, infinite time and space
The transition from one state to the next is not necessarily deterministic
输出样例
The transition from one state to the next is not necessarily deterministic
An algorithm is an effective method that can be expressed within a finite amount of space and time
The transition from one state to the next is not necessarily deterministic
数据规模
0 < L[i] < 512
0 < W[i] < 32
对于 30% 的数据,0 < N < 30,0 < M < 30。
对于 100% 的数据,0 < N < 500,0 < M < 800。
1 package com.mmall.common.program; 2 3 import java.util.ArrayList; 4 import java.util.HashSet; 5 import java.util.List; 6 import java.util.Scanner; 7 8 /** 9 * Created by Workstation on 2017/8/23. 10 * 11 * 字符串的处理问题: 从给定的句子和一段语句,从给定句子中查找到段落中相同的语句 12 */ 13 public class jiri_4 { 14 public static void main (String[] args) { 15 Scanner sc=new Scanner (System.in); 16 17 int n=sc.nextInt (); 18 int m=sc.nextInt(); 19 20 // 向下输入zifuchuan 21 sc.nextLine (); 22 23 String[] senetences=new String[n]; 24 for(int i=0;i<n;i++) 25 { 26 senetences[i]=sc.nextLine (); 27 } 28 29 List<HashSet<String>> sentenceList=new ArrayList<> (); 30 for(int i=0;i<n;i++) 31 { 32 HashSet<String> set=new HashSet<> (); 33 String[] temp=senetences[i].toLowerCase ().split (" "); 34 for(String s:temp) 35 { 36 set.add(s); 37 } 38 sentenceList.add(set); 39 } 40 41 for(int i=0;i<m;i++) 42 { 43 HashSet<String> set = new HashSet<>(); 44 String[] temp = sc.nextLine().toLowerCase().split(" "); 45 for (String s : temp) { 46 set.add(s); 47 } 48 // 遍历List 找到最大相同的单词 49 int max=0,maxIndex=0; 50 51 for(int j=0;j<n;j++) 52 { 53 HashSet<String> targetSentence=sentenceList.get(j); 54 int count=0; 55 for(String s:set) 56 { 57 if(targetSentence.contains (s)) 58 { 59 count++; 60 } 61 } 62 if(count>max) 63 { 64 max=count; 65 maxIndex=j; 66 } 67 System.out.println(senetences[maxIndex]); 68 } 69 } 70 } 71 }