2019,2020年ebay校招的笔试题目。会持续更新。
- diagonals sort
将给定的矩阵按照对角线排序
class Main {
public static void diagSort(int[][] mat) {
int n = mat.length;
for (int d = n-1; d >= -(n-1); d--) {
int start = Math.max(0, -d);
List<Integer> list = new ArrayList();
for (int i = start; i < n && i+d < n && i+d >= 0; i++) {
int j = i+d;
list.add(mat[i][j]);
}
Collections.sort(list);
for (int i = start; i < n && i+d < n && i+d >= 0; i++) {
int j = i+d;
mat[i][j] = list.get(0);
list.remove(0);
}
}
}
public static void main(String[] args) {
int n = 4;
int[][] mat = new int[n][n];
int[] arr = new int[] {8,4,1,4,4,1,4,8,9, 1,3,2,4,5,6,7};
int cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
mat[i][j] = arr[cnt++];
}
}
diagSort(mat);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(mat[i][j] + " ");
}
System.out.println();
}
}
}
- 约瑟夫问题I
输入n和k,n个人循环报数,报到k这个人出列,再从1开始报,直到队列中只剩一个人, 输出出列人的顺序
e.g. n=5, k=3, 输出就是[3, 1, 5, 2]
解题思路:如果只需要输出最后一个留在队列的是谁,是可以运用数学进行简化的。但是这道题要求记住出列人的顺序,则必须模拟游戏过程。
class Main {
public static List<Integer> getResult(int n, int m) {
LinkedList<Integer> list = new LinkedList<Integer>();
LinkedList<Integer> res = new LinkedList<Integer>();
for (int i = 1; i <= n; i++)
list.add(i);
int start = 0;
while (list.size() > 1) {
int delPos = (start + m - 1) % list.size();
res.add(list.remove(delPos));
start = delPos;
}
return res;
}
public static void main(String[] args) {
List<Integer> list = getResult(5, 3);
System.out.println(list);
}
}
- maxArithmeticLength
给定两个数组A,B。问从B中最多选几个数字(可以不选)能让A成为一个等差数列。返回处理后A长度。注意,处理过后A必须是一个等差数列。如果不是一个等差数列,返回-1。
class Main {
public static int maxArithmeticLength(int[] a, int[] b) {
int res = 0;
Set<Integer> factors = new HashSet();
Set<Integer> nums = new HashSet();
for (int num: a)
nums.add(num);
for (int num: b)
nums.add(num);
// 思路是求出等差数列可能的公差,一个个去试验
int n = a.length;
int gcd = -1;
if (n == 1)
factors.add(a[0]);
else {
gcd = a[1] - a[0];
for (int i = 2; i < n; i++)
gcd = gcd(gcd, a[i] - a[i-1]);
}
for (int i = 1; i <= gcd; i++) {
if (gcd % i == 0)
factors.add(i);
}
for (int factor: factors) {
int cur = a[0] + factor;
int length = 1;
while (nums.contains(cur)) {
length++;
cur += factor;
}
// see if can be expanded on the left side
if (cur >= a[n-1]) {
cur = a[0] - factor;
while(nums.contains(cur)) {
cur -= factor;
length++;
}
// only update length here because a now is guaranteed to be an arithmetic array
res = Math.max(res, length);
}
}
return res;
}
private static int gcd(int num1, int num2) {
num1 = Math.abs(num1);
num2 = Math.abs(num2);
while (num1 != num2) {
if (num1 > num2)
num1 = num1 - num2;
else
num2 = num2 - num1;
}
return num1;
}
public static void main(String[] args) {
int[] a = {0, 4, 8, 20};
int[] b = {5, 7, 12, 16, 22};
// int[] a = {1};
// int[] b = { -2, -1, 0, 16, 22};
int res = maxArithmeticLength(a, b);
System.out.println(res);
}
}
- sum to k
input: int[] a, int m, int k
一个array a, 要求在a中找出所有满足条件的continuous subarray,要求 - subarray长度为m
- subarray中有int pair(不能是相同元素)sum to k
ex: a = [2, 6, 4, 7, 1, 3, 5], m = 4, k = 6,output=2
explain:
[2, 6, 4, 7]: 2+4=6
[6, 4, 7, 1]: 没有
[4, 7, 1, 3]: 没有
[7, 1, 3, 5]: 1+5=6
所以return 2
class Main {
private static int sumToK(int[] arr, int m, int k) {
int res = 0;
int n = arr.length;
if (n < m)
return 0;
HashMap<Integer, Integer> map = new HashMap();
for (int r = 0; r < m - 1; r++)
map.put(arr[r], map.getOrDefault(arr[r], 0) + 1);
for (int r = m - 1; r < n; r++) {
int l = r - m;
if (l >= 0) {
int front = map.get(arr[l]);
if (front == 1)
map.remove(arr[l]);
else
map.put(arr[l], front - 1);
}
map.put(arr[r], map.getOrDefault(arr[r], 0) + 1);
for (int key : map.keySet()) {
int val = map.get(key);
if (key * 2 == k && val > 1 || key * 2 != k && map.containsKey(k - key)) {
res++;
break; // 即便数组中有多个满足条件的数对,只能算作一次
}
}
}
return res;
}
public static void main(String[] args) {
int[] a = {2, 6, 4, 7, 1, 3, 5};
System.out.println(sumToK(a, 4, 6));
}
}
- queryRange
给一个数组arr,再给一串query(二维数组形式),每个query都是[l,r,x]形式,寻找arr[l:r+1]之间x出现的次数。所有次数加总之后返回。
class Main {
private static int queryRange(int[]arr, int[][] queries) {
int res = 0;
// HashMap: key is target, val is range
// TreeMap: key is excluded end point (arr[:key]), val is how many times this target appears
HashMap<Integer, TreeMap<Integer, Integer>> map = new HashMap();
for (int[] query: queries) {
int l = query[0];
int r = query[1];
int val = query[2];
TreeMap<Integer, Integer> range = map.getOrDefault(val, new TreeMap());
// 统计在arr[:l]中,target出现的次数
int cnt = 0;
Integer start = range.floorKey(l);
if (start == null)
start = 0;
else
cnt = range.get(start);
for (int i = start; i < l; i++)
if (arr[i] == val)
cnt++;
range.put(l, cnt);
res -= cnt;
// 统计在arr[:r]中,target出现的次数
cnt = 0;
Integer end = range.floorKey(l);
if (end == null)
end = 0;
else
cnt = range.get(end);
for (int i = end; i <= r; i++)
if (arr[i] == val)
cnt++;
range.put(r+1, cnt);
map.put(val, range);
res += cnt;
}
return res;
}
public static void main(String[] args) {
int[] a = {1,1,2,3,2};
int[][] queries = {{1,2,1}, {2,4,2}, {0,3,1}};
System.out.println(queryRange(a, queries));
}
}
- deleteToMakeSmall
Given two strings S and T consisting of digits and lowercase letters, you are allowed to remove only one digit from either string, count how many ways of removal to make S lexicographically smaller than T.
从给定的字符串s,t中删除一个数字(不是字母),使得s的字典序更小。返回有多少种这样的删除方法。
private static int countWays(String s, String t) {
int res = 0;
StringBuilder sb = new StringBuilder();
for(int i = 0; i < s.length(); i++){
sb.setLength(0);
sb.append(s);
if(Character.isDigit(s.charAt(i))){
sb.deleteCharAt(i);
String sub = sb.toString();
if(sub.compareTo(t) < 0)
res++;
}
}
for(int i = 0; i < t.length(); i++){
sb.setLength(0);
sb.append(t);
if(Character.isDigit(t.charAt(i))){
sb.deleteCharAt(i);
String sub = sb.toString();
if(s.compareTo(sub) < 0)
res++;
}
}
return res;
}