Shopee 虾皮
2个小时:10道单选+5道多选+3道编程
第一题:数学问题¶
定义 f(n) 为 n 的最大奇约数, f(1) = 1, f(2) = 1, f(3) = 3, f(4) = 1, f(5) = 5 ..... 以此类推。 定义函数 g(n) = f(1) + f(2) + f(3) .... + f(n) 。 使用Java编程实现g(n),并且时间复杂度尽可能低
输入:4 输出:6
代码实现¶
public class Solution {
/**
* 计算 g(n) = f(1) + f(2) + ... + f(n)
*
* @param n 代表用户数量
* @return g(n) 的值
*/
public long g(int n) {
long sum = 0;
for (int i = 1; i <= n; i++) {
sum += f(i);
}
return sum;
}
/**
* 计算 n 的最大奇约数 f(n)
*
* @param n 需要计算的数
* @return n 的最大奇约数
*/
private int f(int n) {
// 如果 n 是偶数,将其除以 2 直到变为奇数
while (n % 2 == 0) {
n /= 2;
}
return n; // 返回最终的奇数
}
public static void main(String[] args) {
Solution solution = new Solution();
int n = 10; // 可以更改输入值进行测试
System.out.println(solution.g(n)); // 输出 g(n)
}
}
只过了 28%
第二题¶
系统中维护了用户之间的关注关系。现在有n个用户,这些用户的id用1到n的数字表示。这n个用户中可能混入了一个特殊的“运营用户”。已知: 1. 所有的其他用户都关注了这个”运营用户“; 2. 这个”运营用户“没有关注任何人; 3. 这n个用户中只有一个”运营用户“。
给定一个数字n,表示用户的数量;以及数组 relations,表示这n个用户之间的关注信息。\(relations[i] = [a, b]\) 表示用户a关注了用户b。注意:数组relations中不存在重复的元素。 请找到这个特殊的“运营用户”的id,如果不存在,返回-1。
示例:
输入:
3,[[1,3],[2,3]]
输出:
3
说明: 所有的其他用户都关注了用户3,但用户3没有关注任何人
思路分析¶
通过维护一个用户关注情况的计数来解决这个问题。我们可以使用一个数组来记录每个用户关注的数量和被关注的数量。
代码实现¶
import java.util.HashMap;
import java.util.Map;
public class Solution {
/**
* 查找特殊的“运营用户”
*
* @param n 用户数量
* @param relations 关注关系
* @return 运营用户的 ID,如果不存在返回 -1
*/
public int findOperatorUser(int n, int[][] relations) {
int[] followers = new int[n + 1]; // 被关注的计数
int[] following = new int[n + 1]; // 关注的计数
// 处理关注关系
for (int[] relation : relations) {
int a = relation[0];
int b = relation[1];
following[a]++; // 用户 a 关注了用户 b
followers[b]++; // 用户 b 被用户 a 关注
}
// 查找运营用户
for (int i = 1; i <= n; i++) {
// 运营用户的条件
if (following[i] == 0 && followers[i] == n - 1) {
return i; // 找到运营用户
}
}
return -1; // 未找到运营用户
}
public static void main(String[] args) {
Solution solution = new Solution();
int n = 3;
int[][] relations = {{1, 3}, {2, 3}};
System.out.println(solution.findOperatorUser(n, relations)); // 输出 3
}
}
第三题:双指针¶
一条路高低不平,下雨时水会留在低洼的地方。把路面简化成一个直线,用一个数组描述它的高低。
比如 [ 3 2 4 ] 代表一条 3 个单位长的路,高度依次为 3 2 4,则下雨时,它的最大积水可以达到 1 。
实现一个计算最大积水的 函数,输入是代表描述路面高低的数组,输出是最大积水量
示例:
输入: [1,3,2,2,9,1,4]
输出: 5
思路分析¶
通过使用双指针的方法来计算最大积水量。基本思路是利用两个指针从数组两端向中间移动,同时维护左右两边的最高点,以确定当前点的积水量。
代码实现¶
public class Solution {
/**
* 计算最大积水量
*
* @param heights 路面高低的数组
* @return 最大积水量
*/
public int calculateRainWater(int[] heights) {
if (heights == null || heights.length == 0) {
return 0;
}
int left = 0, right = heights.length - 1;
int leftMax = 0, rightMax = 0;
int waterTrapped = 0;
while (left < right) {
if (heights[left] < heights[right]) {
if (heights[left] >= leftMax) {
leftMax = heights[left];
} else {
waterTrapped += leftMax - heights[left];
}
left++;
} else {
if (heights[right] >= rightMax) {
rightMax = heights[right];
} else {
waterTrapped += rightMax - heights[right];
}
right--;
}
}
return waterTrapped;
}
public static void main(String[] args) {
Solution solution = new Solution();
int[] heights = {1, 3, 2, 2, 9, 1, 4};
System.out.println(solution.calculateRainWater(heights)); // 输出 5
}
}
过了 90%