字节跳动
1. 代码校正

package ZJTD;
import java.util.*;
/**
* @author zzm
* @data 2020/5/17 9:04
* 1. 三个同样的字母连在一起,一定是拼写错误,去掉一个的就好啦:比如 helllo -> hello
2. 两对一样的字母(AABB型)连在一起,一定是拼写错误,去掉第二对的一个字母就好啦:比如 helloo -> hello
3. 上面的规则优先“从左到右”匹配,即如果是AABBCC,虽然AABB和BBCC都是错误拼写,应该优先考虑修复AABB,结果为AABCC
*/
public class StrProof {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
for (int i = 0; i < n; i++) {
String s = scanner.nextLine();
StringBuilder sb = new StringBuilder(s.length());
for (int j = 0; j < s.length(); j++) {
if (helper(sb, sb.length(),s.charAt(j))) continue;
sb.append(s.charAt(j));
}
System.out.println(sb.toString());
}
}
private static boolean helper(StringBuilder s, int index,char c) {
if (index < 2 || c != s.charAt(index - 1)) return false;
if (c == s.charAt(index - 2)) return true;
if (index >= 3 && s.charAt(index - 3) == s.charAt(index - 2)) return true;
return false;
}
}
2. 选择三个地点,最大间距不超过 D

思路:左右指针l r(r-l>=3),确定一个区间以l 开始的最大区间,此区间总数 为 (r-l)*(r-l-1)/2, 即从 l+1 到 r 选两个出来。
package ZJTD;
import java.util.*;
/**
* @author zzm
* @data 2020/5/17 10:06
* 1. 我们在字节跳动大街的N个建筑中选定3个埋伏地点。
2. 为了相互照应,我们决定相距最远的两名特工间的距离不超过D。
*/
public class LocationSelect {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int len = scanner.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) nums[i] = scanner.nextInt();
scanner.close();
long res = 0;
int l = 0, r = 2;
while (l < n-2) {
while (r < n && nums[r] - nums[l] <= len) r++;
if (--r - l +1 >= 3) res += (long)(r - l) * (r - l - 1) / 2;
l++;
}
System.out.println(res%99997867);
}
}
3. 麻将
小包最近迷上了一款叫做雀魂的麻将游戏,但是这个游戏规则太复杂,小包玩了几个月了还是输多赢少。
于是生气的小包根据游戏简化了一下规则发明了一种新的麻将,只留下一种花色,并且去除了一些特殊和牌方式(例如七对子等),具体的规则如下:
- 总共有36张牌,每张牌是1~9。每个数字4张牌。
- 你手里有其中的14张牌,如果这14张牌满足如下条件,即算作和牌
- 14张牌中有2张相同数字的牌,称为雀头。
- 除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)
例如:
1 1 1 2 2 2 6 6 6 7 7 7 9 9 可以组成1,2,6,7的4个刻子和9的雀头,可以和牌
1 1 1 1 2 2 3 3 5 6 7 7 8 9 用1做雀头,组123,123,567,789的四个顺子,可以和牌
1 1 1 2 2 2 3 3 3 5 6 7 7 9 无论用1 2 3 7哪个做雀头,都无法组成和牌的条件。
现在,小包从36张牌中抽取了13张牌,他想知道在剩下的23张牌中,再取一张牌,取到哪几种数字牌可以和牌。
思路:当前牌小于4张就加1后判断是否可以胡牌: 当前牌张数大于2则置为头,判断剩下的,否则还原(回溯)--有头后当前张数大于3,则当成刻子,判断剩下的,不成功则还原--同样的方法判断顺子
package ZJTD;
import java.util.*;
/**
* @author zzm
* @data 2020/5/17 10:40
*/
public class Majiang {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] cards = new int[9];
for (int i = 0; i < 13; i++) cards[scanner.nextInt()-1]++;
scanner.close();
int[] helpArr = new int[9];
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 9; i++) {
if (cards[i] < 4) {
System.arraycopy(cards, 0, helpArr, 0, 9);
helpArr[i]++;
if (helper(helpArr, false, 14)) list.add(i + 1);
}
}
if (list.isEmpty()) {
System.out.println(0);
return;
}
StringBuilder sb = new StringBuilder();
sb.append(list.get(0));
for (int i = 1; i < list.size(); i++) sb.append(" " + list.get(i));
System.out.println(sb.toString());
}
private static boolean helper(int[] states, boolean hasHead, int totle) {
if (totle == 0) return true;
if (!hasHead) {
for (int i = 0; i < 9; i++) {
if (states[i] >= 2) {
states[i] -= 2;
if (helper(states, true, totle - 2)) return true;
states[i] += 2;
}
}
return false;
} else {
for (int i = 0; i < 9; i++) {
if (states[i] > 0) {
if (states[i] >= 3) {
states[i] -= 3;
if (helper(states, true, totle - 3)) return true;
states[i] += 3;
}
if (i + 2 < 9 && states[i + 1] > 0 && states[i + 2] > 0) {
states[i]--;
states[i + 1]--;
states[i + 2]--;
if (helper(states, true, totle - 3)) return true;
states[i]++;
states[i + 1]++;
states[i + 2]++;
}
}
}
}
return false;
}
}
4. 找最长的相同特征
小明是一名算法工程师,同时也是一名铲屎官。某天,他突发奇想,想从猫咪的视频里挖掘一些猫咪的运动信息。为了提取运动信息,他需要从视频的每一帧提取“猫咪特征”。一个猫咪特征是一个两维的vector<x, y>。如果x_1=x_2 and y_1=y_2,那么这俩是同一个特征。
因此,如果喵咪特征连续一致,可以认为喵咪在运动。也就是说,如果特征<a, b>在持续帧里出现,那么它将构成特征运动。比如,特征<a, b>在第2/3/4/7/8帧出现,那么该特征将形成两个特征运动2-3-4 和7-8。
现在,给定每一帧的特征,特征的数量可能不一样。小明期望能找到最长的特征运动。
package ZJTD;
import java.util.*;
/**
* @author zzm
* @data 2020/5/21 8:22
*/
public class FeatureSel {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
HashMap<String, Integer> pre = new HashMap<>();
HashMap<String, Integer> now = new HashMap<>();
int max = Integer.MIN_VALUE;
for (int i = scanner.nextInt(); i > 0; i--) {
for (int j = scanner.nextInt(); j > 0; j--) {
for (int k = scanner.nextInt(); k > 0; k--) {
String node = scanner.nextInt()+"-"+scanner.nextInt();
now.put(node, 1 + pre.getOrDefault(node, 0));
max = Math.max(now.get(node), max);
}
pre.clear();
pre.putAll(now);
now.clear();
}
System.out.println(max);
}
scanner.close();
}
}
5. 最少的车票
小明目前在做一份毕业旅行的规划。打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的花销。给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。

以下代码为深度遍历,超时,后续更改
package ZJTD;
import java.util.*;
/**
* @author zzm
* @data 2020/5/17 11:00
*/
public class Tickets {
static int res = Integer.MAX_VALUE;
static int[][] tickets;
static boolean[] used;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
tickets = new int[n][n];
used = new boolean[n];
used[0] = true;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
tickets[i][j] = scanner.nextInt();
}
}
scanner.close();
dfs(0, 1, 0);
System.out.println(res);
}
private static void dfs(int pre, int len, int totle) {
if(totle>res) return;
for (int i = 1; i < used.length; i++) {
if (!used[i]) {
if (len == used.length - 1) {
totle += tickets[pre][i] + tickets[i][0];
res = Math.min(res, totle);
return;
}
used[i] = true;
dfs(i, len + 1, totle + tickets[pre][i]);
used[i] = false;
}
}
}
}
6. 找零钱
Z国的货币系统包含面值1元、4元、16元、64元共计4种硬币,以及面值1024元的纸币。现在小Y使用1024元的纸币购买了一件价值为的商品,请问最少他会收到多少硬币?
package ZJTD;
import java.util.*;
/**
* @author zzm
* @data 2020/5/18 19:40
*/
public class ChangeMoney {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = 1024 - scanner.nextInt();
scanner.close();
int res = 0;
res += n >> 6;
n -= (n >> 6) << 6;
res += n >> 4;
n -= (n >> 4) << 4;
res += n >> 2;
n -= (n >> 2) << 2;
res += n;
System.out.println(res);
}
}
7. 机器人跳建筑
机器人正在玩一个古老的基于DOS的游戏。游戏中有N+1座建筑——从0到N编号,从左到右排列。编号为0的建筑高度为0个单位,编号为i的建筑的高度为H(i)个单位。
起初, 机器人在编号为0的建筑处。每一步,它跳到下一个(右边)建筑。假设机器人在第k个建筑,且它现在的能量值是E, 下一步它将跳到第个k+1建筑。它将会得到或者失去正比于与H(k+1)与E之差的能量。如果 H(k+1) > E 那么机器人就失去 H(k+1) - E 的能量值,否则它将得到 E - H(k+1) 的能量值。
游戏目标是到达第个N建筑,在这个过程中,能量值不能为负数个单位。现在的问题是机器人以多少能量值开始游戏,才可以保证成功完成游戏?
思路: 每一次跳跃后 E = 2E - H; 从后往前,设最终E=0, 则 每一次往前 E = (E+H +1)/2; 注意:+1 是因为最后可能剩一个而不是刚好能量用尽,即 2E-H = 1
package ZJTD;
import java.util.*;
/**
* @author zzm
* @data 2020/5/21 10:13
* 输入描述:第一行输入,表示一共有 N 组数据.
* 第二个是 N 个空格分隔的整数,H1, H2, H3, ..., Hn 代表建筑物的高度
* 输出描述:输出一个单独的数表示完成游戏所需的最少单位的初始能量
* 输入例子1:
* 5
* 3 4 3 2 4
* 输出例子1:
* 4
*/
public class RobotsJump {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] h = new int[n];
for (int i = 0; i < n; i++) h[i] = scanner.nextInt();
scanner.close();
int e = 0;
for (int i = n - 1; i >= 0; i--) e = (e + h[i] + 1) / 2;
System.out.println(e);
}
}

浙公网安备 33010602011771号