刷题漫漫路(二)| 豆包MarsCode AI刷题

50 阅读4分钟

在进行编程练习时,特别是涉及到算法和数据结构的问题,很重要的一点是理解问题的本质,并设计出高效的解决方案。以下是我在解决这个特定问题时的一些心得体会,包括代码实现的思路以及优化思考。

问题分析

题目要求在给定一个长度为 n 的数列 a 中,找到一对不同的索引 (i, j),使得它们之间的贡献值最大。贡献值的计算方式为:两数之和乘以它们之间的最短距离。这个最短距离考虑了数列的环形特性,所以在计算时需要考虑到环的情况。

思路和实现步骤

  1. 定义最短距离:对于环形数组 (也可以看作是循环链表),在任何两个元素 i 和 j 之间,最短距离可以通过 min(abs(i - j), n - abs(i - j)) 计算得到。
  2. 计算贡献值:对于每一对索引 (i, j),其贡献值为 (a[i] + a[j]) * dist,其中 dist 是最短距离。
  3. 遍历所有索引对:我选择了两层嵌套循环来遍历所有可能的 (i, j) 对,并计算相应的贡献值。
  4. 更新最大贡献值:在计算贡献值的同时,保持对已经找到的最大贡献值的记录。

以下是我实现的代码:

python
def solution(n: int, a: list) -> int:  
    max_contribution = 0  
    
    # 遍历所有可能的 (i, j) 对  
    for i in range(n):  
        for j in range(n):  
            if i != j:  
                # 计算最短距离  
                dist = min(abs(i - j), n - abs(i - j))  
                
                # 计算贡献值  
                contribution = (a[i] + a[j]) * dist  
                
                # 更新最大贡献值  
                if contribution > max_contribution:  
                    max_contribution = contribution  
    
    return max_contribution  

if __name__ == '__main__':  
    print(solution(n = 3, a = [1, 2, 3]) == 5)  # 2 + 3 with distance 1  
    print(solution(n = 4, a = [4, 1, 2, 3]) == 12)  # 4 + 3 with distance 1  
    print(solution(n = 5, a = [1, 5, 3, 7, 2]) == 24)  # 7 + 5 with distance 1  

代码解析

  1. 初始化最大贡献值: max_contribution 被初始化为 0,因为没有任何比较时的初始值。
  2. 两层循环遍历:使用 for i in range(n) 和内层的 for j in range(n) 循环遍历所有大小为 n 的数组中的所有可能的索引组合。这里需要使用 if i != j 确保不计算同一元素的贡献。
  3. 计算和更新:在内层循环中,我们首先计算最短距离 dist,然后使用这个值和当前元素的和来计算贡献值。接着,通过比较当前的贡献值与 max_contribution,更新最大贡献值。

心得体会

  1. 遍历组合的有效性:虽然使用双重循环的方式简单直观,但是这种方法在 n 较大时会导致 O(n^2) 的时间复杂度。经过这次练习,我意识到对于 n 较大的情况,这种方法可能会造成性能瓶颈。
  2. 数学思考的必要性:在处理类似“环形数组”的问题时,考虑数学性质和规律是关键。通过合理的方法,可以降低时间复杂度,尤其是在需要多次计算相同属性的情况下。
  3. 测试用例的重要性:通过多种样例的验证,能够确保代码的正确性。在这段实现中,我设计了几个测试用例,包括不同长度和不同元素的数组,帮助我验证逻辑的正确性。
  4. 后续优化思考:虽然当前的实现满足题目的要求,但我意识到需要进一步优化,考虑如何减少计算贡献值的次数。例如,可以存储数组的求和、最大值等,利用这些预计算结果来提高效率。
  5. 编程习惯与思维方式:在整个编程过程中,良好的编程习惯和清晰的思维方式是编写有效代码的基础。按照清晰的逻辑和步骤进行编程,有助于减少错误并提高代码可读性。

总结

通过这次练习,我不仅巩固了对双重循环和数组操作的理解,还提升了对环形数组等特殊情况的处理能力。这对于以后的编程挑战是一个很好的锻炼,同时也鼓励我继续寻求更高效的解决方案。在未来的编程中,我将会更加关注算法复杂度的分析和优化,力求在保证正确性的同时提升性能。