微软8.13笔试
1、int数组,用一次过滤器可以将里面某个数过减少一半,求最小过滤次数,使得数组和小于等于原来数组和的一半。
例:(1)、[1,2],答案是2。第一次过滤2,数组变为[1,1],和是2>(1+2)/2=1.5. 第二次过滤,数组变为[0.5,1],和是1.5==(1+2)/2=1.5.
(2)、[1,5],答案是2。第一次过滤5,数组变为[1,2.5],和是3.5>(1+5)/2=2.5. 第二次过滤,数组变为[1,1.25],和是2.25<(1+5)/2=2.5.
思路:模拟。优先级队列,每次将最大的数出堆,减半入堆,同时记录最大和和过滤次数,满足条件时终止循环,返回结果。
难点:想到每次过滤最大的这个数。
时空复杂度:nlogn,n。将数组中每个元素放入大根堆中,时间复杂度时nlogn。创建大根堆需要O(n)空间。
解法:
@Test
public void test() {
int solution1 = solution(new int[]{3, 3});
int solution2 = solution(new int[]{1, 3});
System.out.println(solution1);
System.out.println(solution2);
}
public int solution(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int res = 0;
// 1、创建大根堆
PriorityQueue<Double> pq = new PriorityQueue<>((a, b) -> (b.compareTo(a)));
double oldSum = 0;
for (int num : nums) {
pq.add((double) num);
oldSum += num;
}
// 2、遍历,更新大根堆,当前和,过滤次数
double curSum = oldSum;
while (curSum > oldSum / 2) {
Double poll = pq.poll();
pq.add(poll / 2);
res++;
curSum -= poll / 2;
}
return res;
} 2、两个int型数组,分别是分子和分母,选择一对分数使得和为1,求有多少对。
例:【1,1,1】,【2,2,2】,答案是3. 【1,2,2】,【3,2,3】,答案是1.
思路:两数之和。
难点:分数之间的减法
时空复杂度:n,n。
解法:
@Test
public void test() {
int solution1 = solution(new int[]{1, 1, 2}, new int[]{3, 2, 3});
System.out.println(solution1);
}
public int solution(int[] nums1, int[] nums2) {
int res = 0;
String[] strs = new String[nums1.length];
for (int i = 0; i < strs.length; i++) {
strs[i] = String.format("%s/%s", nums1[i], nums2[i]);
}
// 两数之和
HashMap<String, Integer> map = new HashMap<>();
for (int i = 0; i < strs.length; i++) {
String key = strs[i];
String target = oneMinusKey(key);
if (map.containsKey(target)) {
res += map.get(target);
}
map.put(key, map.getOrDefault(key, 0) + 1);
}
return res;
}
public String oneMinusKey(String x) {
char up = (char) (x.charAt(2) - x.charAt(0) + '0');
char down = x.charAt(2);
return String.format("%s/%s", up, down);
} 3、int数组,int[i]代表第i天的价格,每隔y天付一次钱,一共要做x次。求最小付钱数。 例:[1,4,2,3],1+2与4+3的最小值。
思路:暴力,求出可以开始遍历的区间,从区间的每个起始位置开始,向后累加x次,同时调整最小值。
难点:不要想复杂,刚开始我想回溯,但肯定超时。后面发现只要向后看就可以了。
时空复杂度:n2,1
解法:
@Test
public void test() {
int solution = solution(new int[]{1, 4, 3, 2}, 1, 2);
System.out.println(solution);
}
public int solution(int[] nums, int x, int y) {
int res = Integer.MAX_VALUE;
int maxStart = nums.length - (x - 1) * y - 1;
for (int i = 0; i < maxStart; i++) {
int curSum = 0, index = i;
for (int j = 0; j < x; j++) {
curSum += nums[index];
index += y;
}
res = Math.min(res, curSum);
}
return res;
}
查看10道真题和解析