Skip to content

zy面试题

题目1

1、电商产品有颜色(红、蓝、黑)、尺寸(S、M、L)等变体信息,买家购买一个红色中码的商品对应的变体名为:红_M。那么给定一组变体信息,用程序生成所有变体组合数据。

变体示例:Color: Red,Green Size: S,M Style: A

变体组合结果:Red_S_A; Red_M_A; Green_S_A; Green_M_A

//测试用例 
var list = new List<string[]>{
 new string[]{"Red","Green"},
 new string[]{"S","M"},
 new string[]{"A"}
};
var result = Combine(list);
//期望result为:Red_S_A; Red_M_A; Green_S_A; Green_M_A
public List<string> Combine(List<string[]> list){ … }
解答
csharp
public static List<string> Combine(List<string[]> list)
{
    List<string> result = new List<string>();
    int[] indices = new int[list.Count]; // 用于跟踪每个字符串数组中当前选取的元素的索引

    while (true)
    {
        string combined = "";
        for (int i = 0; i < list.Count; i++)
        {
            combined += "_" + list[i][indices[i]]; // 将当前索引对应的元素添加到组合中
        }
        result.Add(combined); // 将组合添加到结果列表中

        // 更新索引
        int j = list.Count - 1;
        while (j >= 0 && indices[j] == list[j].Length - 1)
        {
            indices[j] = 0;
            j--;
        }

        // 检查是否所有索引都已经达到最大值
        if (j < 0)
        {
            break;
        }

        indices[j]++; // 增加索引
    }

    return result;
}

方式2

csharp
public static List<string> Combine(List<string[]> list, int index = 0, string prefix = "")
{
    List<string> result = new List<string>();
    if (index < list.Count)
    {
        foreach (var option in list[index])
        {
            var newPrefix = prefix + "_" + option;
            result.AddRange(Combine(list, index + 1, newPrefix));
        }
    }
    else
    {
        result.Add(prefix.Trim('_'));
    }
    return result;
}

题目2

2、内部系统的产品库中有一个产品拥有三个维度的变体,分别是:Color、Size 和 Style。现在要将其上传到平台 A,但平台 A 仅支持两个维度的变体,因此需要对变体进行降维。那么给定一组变体信息,用程序实现变体降维操作。

变体示例: Color: Red,Green Size: S,M Style: A,B

降维后:Color: Red,Green Size: S_A,S_B,M_A,M_B

csharp
var pair = new Dictionary<string, List<string>> {
 {"Color",new List<string>{ "Red","Green" }},
 {"Size",new List<string>{ "S","M" }},
 {"Style",new List<string>{ "A","B" }},
};
var result = Reduce(pair);

public Dictionary<string, List<string>> Reduce(Dictionary<string, List<string>> pair){...}
解答

using System; using System.Collections.Generic; using System.Linq;

class Program { static void Main() { // 定义变体维度 string[] colors = { "Red", "Green" }; string[] sizes = { "S", "M" }; string[] styles = { "A", "B" };

    // 降维操作
    Dictionary<string, string[]> reducedDimensions = ReduceDimensions(colors, sizes, styles);
    
    // 打印降维后的变体
    Console.WriteLine("Color: " + string.Join(",", reducedDimensions["Color"]));
    Console.WriteLine("Size: " + string.Join(",", reducedDimensions["Size"]));
}

static Dictionary<string, string[]> ReduceDimensions(string[] colors, string[] sizes, string[] styles)
{
    var reduced = new Dictionary<string, string[]>
    {
        { "Color", colors },
        { "Size", sizes.SelectMany(size => styles.Select(style => size + "_" + style)).ToArray() }
    };

    return reduced;
}

}

题目3

3、在向电商平台上传产品时,一般使用异步上传。数据库中会保存所有的待上传信息,并由后台任务执行上传操作。已有的任务表设计如下:

列名类型必填备注
idint已勾选自增任务编号
create_timedatetime已勾选创建时间
useridint已勾选用户编号
productidint已勾选产品编号

请对该表进行补充,以实现以下内容:

  • 1.任务排队执行。
解答

为了实现任务排队和支持并发上传,我们需要添加一些字段来控制任务的状态和并发:

列名类型必填备注
statusvarchar已勾选任务状态,如:待处理、处理中、已完成、失败
attempt_countint已勾选重试次数,初始为0
concurrencyint并发控制,标识当前任务可以由哪个实例处理
  • status:用于跟踪任务的当前状态。
  • attempt_count:用于记录任务已经重试的次数。
  • concurrency:可以用于实现锁或者信号量机制,确保任务不会被多个实例同时处理。
  • 2.支持并发上传。可以通过增加任务机实例的方式提升上传速度。
解答

为了确保任务不会被多个任务机同时执行,可以使用乐观锁或者悲观锁机制:

列名类型必填备注
versionint乐观锁版本号
  • version:每次任务更新时版本号增加,用于检测在任务处理期间是否发生了冲突。
  • 3.任务不会同时被多个任务机执行。
解答

为了实现超时和异常重试,我们需要记录任务的开始时间和最后更新时间:

列名类型必填备注
start_timedatetime任务开始执行时间
last_updateddatetime最后更新时间,用于超时检测
  • start_time:记录任务开始执行的时间。
  • last_updated:每次任务执行时更新,用于检测任务是否超时。
  • 4.任务执行时间超过 15 分钟,或者执行异常时,要放回任务表继续重试。
解答

可以通过增加一个重试时间和最大尝试次数的字段来控制重试机制:

列名类型必填备注
next_retrydatetime下次重试时间
max_attemptsint最大尝试次数
  • next_retry:根据重试间隔和尝试次数计算的下次重试时间。
  • max_attempts:设置最大尝试次数,超过该次数后不再重试。
  • 5.重试间隔 5 分钟,最多重试三次。
解答

题目4

4、随着用户量的增多,渐渐出现了若干“头部用户”,这些头部用户的上传量占到系统总量的 80% 。 有客户反应上传很慢,要等很久才能上传完成。经排查是因为这些“头部用户”的上传任务积压过多造成的。 请在上一步骤的设计表上再进行扩充或创建新的表以实现以下功能:

  • 4.1 在排队执行时要关注用户编号
解答

为了在排队时考虑用户编号,我们可以引入优先级队列的概念,根据用户编号对任务进行排序:

  • 引入优先级列:在任务表中增加一个优先级列,可以基于用户编号或其他业务规则来设置。
  • 优先级列(Priority):int类型,数值越小优先级越高,可以根据用户的历史表现或重要性来动态调整。
列名类型必填备注
priorityint已勾选任务优先级

后台任务调度器可以根据优先级列来决定任务的执行顺序。

  • 4.2 如果任务涉及多个用户,不能让单个用户占用全部上传资源
解答

为了避免单个用户占用全部上传资源,我们可以引入资源配额管理:

  • 用户配额表:创建一个新表来管理每个用户的上传配额。
表名列名类型必填备注
UserQuotauseridint已勾选用户编号
quotaint已勾选用户允许的最大并发任务数
usedint已勾选当前已使用的并发任务数
  • 并发控制逻辑:在任务执行前,检查用户配额表中的used字段,确保不超过quota
  • 任务完成时:更新用户配额表,减少used字段。
  • 4.3 如果任务仅对应一个用户,则可以让其利用全部上传资源
解答

对于只涉及单个用户的任务,我们允许其利用全部可用的上传资源:

  • 单用户任务标识:在任务表中增加一个标识,用于区分任务是否仅涉及单个用户。
列名类型必填备注
single_userbit是否为单个用户的任务,0为否,1为是
  • 资源分配逻辑:如果是单个用户的任务(single_user为1),则允许其使用用户配额表中定义的全部配额。
  • 并发任务数:对于单个用户的任务,used字段可以等于quota,即用户可以利用全部资源。