今天的第二题得用二分加数组写,拿HashSet写不太友好呀。
本题链接
这道题简单题一般就是暴力,也不会太为难你,但是不要那么老实的镇区写暴力,这道题带点贪心的意思,反正是移动,最后的结果只要每一个字符的值mod个数==0的话就返回true,否则返回false。
class Solution {
public boolean makeEqual(String[] words) {
int[] arr = new int[26];
int n = words.length;
for(String s: words){
char[] c = s.toCharArray();
for(char ch: c){
arr[ch-'a']++;
}
}
for(int i = 0; i < 26; i++){
if(arr[i]%n!=0){
return false;
}
}
return true;
}
}
这道题卡的很恶心,主要用到了两个知识点:二分和子序列
下面先贴一下模板:
最小值最大:
//check(mid)是对mid处的数进行判断。
//若符合right,答案就在left。即binarySearch1
//若符合left,答案就在right。即binarySearch2
int binarySearch1(int l,int r){
while(l < r){
int mid = l + (r - 1) / 2; //mid那里不+1
if(check(mid)) r = mid; //先r
else l = mid + 1; //后l l+1
}
return l; //二分到最后一个,即l==r时,为所求
}
int binarySearch2(int l,int r){
while(l < r){
int mid = l + (r - l) / 2 + 1; //mid那里要+1
if(check(mid)) l = mid; //先l
else r = mid - 1; //后r r-1
}
return l; //二分到最后一个,即l==r时,为所求
}
子序列
import java.util.*;
class Main{
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] arr = new int[n];
int[] nums = new int[m];
for(int i = 0; i < n; i++){
arr[i] = sc.nextInt();
}
for(int i = 0; i < m; i++){
nums[i] = sc.nextInt();
}
int res = 0,j = 0;
for(int i = 0; i < m; i++){
if(j < n &&arr[j]==nums[i]){
j++;
}
}
if(j==n){
System.out.println("Yes");
}else{
System.out.println("No");
}
}
}
本题解法:
class Solution {
boolean[] st = new boolean[100010];
public int maximumRemovals(String s, String p, int[] removable) {
int l = 0,r = removable.length;
while(l < r){
int mid = (l+r+1)/2;
if(check(mid,s,p,removable)){
l = mid;
}else{
r = mid - 1;
}
}
return l;
}
boolean check(int mid,String s,String p,int[] re){
Arrays.fill(st,false);
for(int i = 0; i < mid;i++){
st[re[i]] = true;
}
int j = 0;
for(int i = 0; i < s.length(); i++){
if(st[i]){
continue;
}
if(j < p.length()&& s.charAt(i)==p.charAt(j)){
j++;
}
}
return j == p.length();
}
}
这道题是一个贪心题,先看数据范围10的5次方,因此不是个贪心就是个DP。显而易见是个贪心,因此先把>= 目标数组对应位置的数组去掉,然后判断对应位置上有没有目标数组的值。
class Solution {
public boolean mergeTriplets(int[][] triplets, int[] target) {
ArrayList<int[]> list = new ArrayList<>();
for(int[] arr: triplets){
boolean flag = false;
for(int i = 0; i < 3; i++){
if(arr[i]>target[i]){
flag = true;
}
}
if(!flag&&(arr[0] == target[0]||arr[1] == target[1]||arr[2] == target[2])){
list.add(arr);
}
}
if(list.size()==0){
return false;
}
boolean[] flag = new boolean[3];
for(int[] arr:list){
for(int i = 0; i < 3; i++){
if(arr[i] ==target[i]){
flag[i] = true;
}
}
}
for(int i = 0; i < 3; i++){
if(!flag[i]){
return false;
}
}
return true;
}
}
本题较难,参考题解:
定义 \textit{dp}(n,\textit{fi},\textit{se})dp(n,fi,se) 为人数为 nn,两名选手位置分别在 \textit{fi}fi 和 \textit{se}se 时的最早回合数和最晚回合数。
转移时,枚举下一轮两名选手的位置。
为简化判断,可以在枚举前处理一下两名选手的位置:若两名选手均在中间位置右侧,或者第二名选手比第一名选手更靠近端点,则将第一名选手的位置映射到第二名选手关于中间位置对称的位置,第二名选手同理。这样交换后,第一名选手必位于中间位置左侧,且第一名选手比第二名选手更靠近端点。
然后枚举第一名选手左侧保留多少个人,以及第一名选手和第二名选手中间保留多少个人,这样就可以得到下一轮两名选手的位置。
作者:endlesscheng
class Solution {
int[][][][] map;
void walk(int n, int p1, int p2, int p11, int p21, int index, int[] res) {
if(index + index >= n-1) {
int[] r = solve((n+1)>>>1, p11, p21);
res[0] = Math.min(res[0], r[0]);
res[1] = Math.max(res[1], r[1]);
} else {
int index2 = n-1-index;
int m = 0;
if(index != p1 && index != p2) {
if(index < p1) {
walk(n, p1, p2, p11-1, p21-1, index+1, res);
m = 1;
}else if(index < p2) {
walk(n, p1, p2, p11, p21-1, index+1, res);
m = 2;
} else {
walk(n, p1, p2, p11, p21, index+1, res);
m = 3;
}
}
if(index2 != p1 && index2 != p2) {
if(index2 < p1) {
if(m != 1)
walk(n, p1, p2, p11-1, p21-1, index+1, res);
} else if(index2 < p2) {
if(m != 2)
walk(n, p1, p2, p11, p21-1, index+1, res);
} else {
if(m != 3)
walk(n, p1, p2, p11, p21, index+1, res);
}
}
}
}
int[] solve(int n, int p1, int p2) {
int[] res = map[n][p1][p2];
if(res != null)
return res;
if(p1 + p2 == n-1) {
res = new int[] {1,1};
} else {
res = new int[] {n, 0};
walk(n, p1, p2, p1, p2, 0, res);
res[0] ++;
res[1] ++;
}
map[n][p1][p2] = res;
return res;
}
//..p1..p2..
//
public int[] earliestAndLatest(int n, int p1, int p2) {
p1--;
p2--;
if(p1 > p2) {
int x = p1;
p1=p2;
p2 = x;
}
this.map = new int[n+1][n][n][];
return solve(n, p1, p2);
}
}