rust学习笔记13-18. 四数之和

上一篇已经说到了两数之和,索性将三数之和与四数之和一起都复习一下

15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != 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] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

复制代码
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

复制代码
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

解答

rust 复制代码
//双指针
pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {

    let mut resultList:Vec<Vec<i32>> =Vec::new();
    let mut nums2 = nums.clone();
    // 先进行排序
    nums2.sort();
    for i in 0..nums2.len() {
        // 如果最小的都大于0,那就没有集合,直接返回
        if nums2[i] > 0 {
            return resultList;
        }
        // 去重
        if i > 0 && nums2[i] == nums2[i - 1] {
            continue;
        }
        
        let mut  left = i + 1;
        let mut  rigth = nums2.len() - 1;
        while left < rigth {
            let n = nums2[i] + nums2[left] + nums2[rigth];
            if n > 0 {
                rigth -= 1;
            }else if  n < 0  {
                left += 1; 
            }else {
                resultList.push(vec![nums2[i],nums2[left],nums2[rigth]]);
                //右侧去重
                while left < rigth && nums2[rigth] == nums2[rigth - 1] {
                    rigth -= 1;
                }
                //左侧去重
                while left < rigth && nums2[left] == nums2[left + 1] {
                    left += 1;
                }
                rigth -= 1;
                left += 1; 
            }  
        }
    }

    return  resultList;
        
}


//三数之和
fn main() {
    let nums = vec![-1,0,1,2,-1,-4];
    let res = three_sum(nums);
    println!("{:?}", res);
}

18. 四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复 的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abcd 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

示例 1:

复制代码
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

复制代码
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

提示:

  • 1 <= nums.length <= 200
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109

四数之和与三数之和一样,无非多了一层循环,具体解法如下

rust 复制代码
pub fn four_sum(nums: Vec<i32>, target: i32) -> Vec<Vec<i32>> {
    let mut resultList:Vec<Vec<i32>> =Vec::new();
    let mut nums2 = nums.clone();
    // 先进行排序
    nums2.sort();
    for i in 0..nums2.len() {
        //剪枝
        if nums2[i] > target && nums2[i] >= 0 {
            break;
        }

        // 第一层去重
        if i > 0 && nums2[i] == nums2[i - 1] {
            continue;
        }

        for j in  i+1..nums2.len() {
            // 解释一下,i=nums[0], j=nums[1], left=nums[2], rigth=nums[3]
            // 第二层剪枝
            if nums2[i] + nums2[j] > target && nums2[i] + nums2[j] >= 0 {
                break;
            }
            // 第二层去重
            if j > i + 1 && nums2[j] == nums2[j - 1] {
                continue;
            }

            let mut  left = j + 1;
            let mut  rigth = nums2.len() - 1;
            while left < rigth {
                let n: i32 = nums2[i] + nums2[j] + nums2[left] + nums2[rigth];
                if n > target {
                    rigth -= 1;
                }else if  n < target  {
                    left += 1; 
                }else {
                    resultList.push(vec![nums2[i], nums2[j], nums2[left],nums2[rigth]]);
                    //右侧去重
                    while left < rigth && nums2[rigth] == nums2[rigth - 1] {
                        rigth -= 1;
                    }
                    //左侧去重
                    while left < rigth && nums2[left] == nums2[left + 1] {
                        left += 1;
                    }
                    rigth -= 1;
                    left += 1; 
                }  
            }
        }

    }

    return resultList;
        
}
fn main() {
    let nums = vec![1,0,-1,0,-2,2];
    let res = four_sum(nums, 0);
    println!("{:?}", res);
}

总结,两数之和与三数之和、四数之和解法不一样,主要是因为返回值,两数之和要返回下角标不能做排序,用hashmap合适,而三数之和、四数之和是要求返回结果集且不能重复,需要对数组进行排序,用双指针更适合。

相关推荐
你的微笑像拥抱5 分钟前
vscode 源代码管理
笔记
技术干货贩卖机6 分钟前
0基础 | 看懂原理图Datasheet 系列1
笔记·stm32·单片机·嵌入式硬件·学习
陈无左耳、19 分钟前
HarmonyOS学习第18天:多媒体功能全解析
学习·华为·harmonyos
柒十三.1 小时前
江科大51单片机笔记【14】直流电机驱动(PWM)
笔记·嵌入式硬件·51单片机
晴空对晚照1 小时前
[动手学习深度学习]13.丢弃法 Dropout
人工智能·深度学习·学习
Mapmost1 小时前
【从零打造视觉盛宴·进阶篇】城市场景建模避坑指南,常见问题轻松破!
笔记·强化学习·数据可视化
汤姆和佩琦1 小时前
LLMs基础学习(一)概念、模型分类、主流开源框架介绍以及模型的预训练任务
人工智能·学习·算法·分类·数据挖掘
宇寒风暖1 小时前
HTML 表单详解
前端·笔记·学习·html