Bootstrap

实习冲刺第二十九天

15.三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

思路详解:

1. 首先使用sort对数组进行排序

2. 遍历排序后的数组,固定好一个元素nums[i],将left指针初始化为i+1,将right指针初始化为数组末尾。

3. 当left < right时,

    - 计算三个元素的和sum = nums[i] + nums[left] + nums[right]。
    - 如果sum等于零,将这个三元组[nums[i], nums[left], nums[right]]添加到结果集中。
    - 如果sum小于零,说明需要增大和,将left指针右移一位。
    - 如果sum大于零,说明需要减小和,将right指针左移一位。
    - 注意,如果出现重复的元素,需要跳过,以避免重复的三元组。
4. 继续遍历数组,直到遍历完所有的元素。

代码详解:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end()); // 对数组进行排序,以便后续操作
        vector<vector<int>> answer; // 存储结果
          for (int i = 0; i < n - 2; i++) { //遍历数组,固定第一个元素
            // 避免重复的固定元素
            if (i > 0 && nums[i] == nums[i - 1])
                continue;
            int left = i + 1; // 左指针指向固定元素的下一位
            int right = n - 1; // 右指针指向数组末尾
            while (left < right) {//保证两个指针不相遇,相遇说明所有情况以及遍历
                int sum = nums[i] + nums[left] + nums[right]; // 计算三个元素的和
                if (sum < 0) { // 如果和小于零,说明需要增大和,左指针右移一位
                    left++;
                }
                else if (sum > 0) { // 如果和大于零,说明需要减小和,右指针左移一位
                    right--;
                }
                else { // 和等于零,找到满足条件的三元组
                    answer.push_back({nums[i], nums[left], nums[right]}); // 将三元组添加到结果中
                    //如果左指针的下一个元素和本身相同说明我们以及考虑过这个数字,则跳过
                    while (left < right && nums[left] == nums[left + 1])
                        left++;
                    //右指针同理
                    while (left < right && nums[right] == nums[right - 1])
                        right--;
                    //当我们判断完一个三元组后让指针移动指向新的元素,这样可以避免产生相同的三元组
                    left++; 
                    right--; 
                }
            }
        }  
        return answer;
    }
};

面经

  1. 什么是c++中的模板特化和偏特化,如何实现他们
  • 模板特化是指为特定的数据类型提供一个专门的模板定义。当我们希望对于某些特定的类型,模板有不同的实现时,可以使用模板特化。
template <>
void swap<int>(int& a, int& b) {
    // 更高效的位操作交换
    if (a != b) {
        a ^= b;
        b ^= a;
        a ^= b;
    }
}//这里的template <>表示这是一个特化,而void swap<int>(int& a, int& b)表示这是针对int类型的特化实现。
  • 偏特化是指对模板参数进行更具体的限制,而不是完全指定一个特定的类型。偏特化可以应用于类模板和函数模板,但通常更多地用于类模板。
template <typename T, typename Allocator>
class Storage {
    // ...
};

template <typename T>
class Storage<T, allocator<T>> {
    // 针对allocator<T>的优化实现
    // ...
};
//在这个例子中,我们没有为T提供一个特定的类型,而是为Allocator参数提供了一个特定的类型allocator<T>,这就是偏特化的一个例子。

;