【Array-medium】15. 3Sum 三个数相加等于 0

本文详细解析了LeetCode上的3Sum问题,提供了一种有效的解决方案,包括数组排序、双指针技巧以及如何避免重复解。通过示例代码展示了如何在给定数组中找出所有三个数相加和为0的序列。

1. 题目原址

https://leetcode.com/problems/3sum/

2. 题目描述

在这里插入图片描述

3. 题目大意

给定一个数组,返回所有三个数相加和为0的序列

4. 解题思路

  • 首先将数组排序
  • 如果当前元素大于0,那么就不能存在三个数的和为0的序列,直接返回null即可。
  • 为了保证不加入重复的 list,因为是有序的,所以如果和前一个元素相同,只需要继续后移就可以
  • i==0,正常寻找另两个数;i>0且当前元素不同于前一个元素,正常寻找前两个值

5. AC代码

class Solution {
    public List<List<Integer>> threeSum(int[] num) {
        Arrays.sort(num);
        // 在需要频繁读取集合中的元素时,使用ArrayList效率较高,而在插入和删除操作较多时,使用LinkedList效率较高。
        // 对于此题来说两种都可以。
        List<List<Integer>> res = new LinkedList<List<Integer>>();
        for (int i = 0; i+2 < num.length; i++) {
            // if num[i] already larger than 0, lo and hi will both larger than 0
            if(num[i] > 0) break;
            // 为了保证不加入重复的 list,因为是有序的,所以如果和前一个元素相同,只需要继续后移就可以
            // i==0,正常寻找另两个数;i>0且当前元素不同于前一个元素,正常寻找前两个值
            // i>0且当前元素与前一个元素相同,直接进入下一循环,否则本次找到的三个数会与上个循环的三个数完全相同
            if (i == 0 || (i > 0 && num[i] != num[i-1])) {
                // lo将从前往后遍历,且不与i相同;hi为从后往前遍历
                int lo = i+1;
                int hi = num.length-1;
                int sum = 0 - num[i];

                while (lo < hi) {
                    if (num[lo] + num[hi] == sum) {

                        res.add(Arrays.asList(num[i], num[lo], num[hi]));
                        // 重复元素跳过
                        while (lo < hi && num[lo] == num[lo+1]) lo++;
                        while (lo < hi && num[hi] == num[hi-1]) hi--;
                        lo++;
                        hi--;
                    }
                    else if(num[lo] + num[hi] < sum) lo++;
                    else hi--;
                }
            }
        }
        return res;
    }
}

6. 相似题型

【1】 1. Two Sum 题目原址:https://leetcode.com/problems/two-sum/
【2】 15. 3Sum 题目原址: https://leetcode.com/problems/3sum/
【3】 18. 4Sum 题目原址: https://leetcode.com/problems/4sum/
【4】167. Two Sum II - Input array is sorted 题目原址: https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
【5】 560. Subarray Sum Equals K 题目原址:https://leetcode.com/problems/subarray-sum-equals-k/
【6】 653. Two Sum IV - Input is a BST 题目原址:https://leetcode.com/problems/two-sum-iv-input-is-a-bst/
【7】 16. 3Sum Closest 题目原址: https://leetcode.com/problems/3sum-closest/

%% 步骤1: 数据准备与预处理 % 读取Excel数据 data = readtable(&#39;imputed_data.xlsx&#39;); % 替换为您的Excel文件路径 % 分离特征和标签 features = table2array(data(:, 1:end-1)); % 前N-1列为特征 labels = table2array(data(:, end)); % 最后一列为标签 % 数据标准化 mu = mean(features, 1); sigma = std(features, 0, 1); features = (features - mu) ./ sigma; % 数据集划分 cv = cvpartition(size(features,1), &#39;HoldOut&#39;, 0.2); XTrain = features(cv.training, :); YTrain = labels(cv.training, :); XTest = features(cv.test, :); YTest = labels(cv.test, :); % 转换为深度学习数据集格式 dsTrain = arrayDatastore(XTrain, &#39;IterationDimension&#39;, 1); dsTrainLabels = arrayDatastore(YTrain); dsTrain = combine(dsTrain, dsTrainLabels); %% 步骤2: 构建五残差块网络架构 % 输入层 (根据实际数据维度设置) inputSize = 10; % 根据错误提示设置 inputLayer = featureInputLayer(inputSize, &#39;Name&#39;, &#39;input&#39;); % 创建层图 lgraph = layerGraph(inputLayer); % 添加残差块 (显式指定输入/输出维度) lgraph = addResidualBlock(lgraph, &#39;block1&#39;, inputSize, 64, &#39;input&#39;); lgraph = addResidualBlock(lgraph, &#39;block2&#39;, 64, 128, &#39;block1_out_relu&#39;); lgraph = addResidualBlock(lgraph, &#39;block3&#39;, 128, 256, &#39;block2_out_relu&#39;); lgraph = addResidualBlock(lgraph, &#39;block4&#39;, 256, 512, &#39;block3_out_relu&#39;); lgraph = addResidualBlock(lgraph, &#39;block5&#39;, 512, 512, &#39;block4_out_relu&#39;); % 添加输出层 outputLayers = [ fullyConnectedLayer(10, &#39;Name&#39;, &#39;fc_final&#39;) softmaxLayer(&#39;Name&#39;, &#39;softmax&#39;) classificationLayer(&#39;Name&#39;, &#39;output&#39;) ]; lgraph = addLayers(lgraph, outputLayers); lgraph = connectLayers(lgraph, &#39;block5_out_relu&#39;, &#39;fc_final&#39;); % 可视化网络结构 analyzeNetwork(lgraph) %% 步骤3: 残差块函数定义 function lgraph = addResidualBlock(lgraph, blockName, inputSize, outputSize, inputLayerName) % 主路径 mainLayers = [ fullyConnectedLayer(outputSize, &#39;Name&#39;, [blockName &#39;_fc1&#39;]) batchNormalizationLayer(&#39;Name&#39;, [blockName &#39;_bn1&#39;]) reluLayer(&#39;Name&#39;, [blockName &#39;_relu1&#39;]) fullyConnectedLayer(outputSize, &#39;Name&#39;, [blockName &#39;_fc2&#39;]) batchNormalizationLayer(&#39;Name&#39;, [blockName &#39;_bn2&#39;]) ]; % 跳跃连接处理 if inputSize == outputSize % 维度匹配时使用恒等层 shortcutLayers = IdentityLayer([blockName &#39;_identity&#39;]); shortcutOutput = [blockName &#39;_identity&#39;]; else % 维度不匹配时添加调整层[^1] shortcutLayers = [ fullyConnectedLayer(outputSize, &#39;Name&#39;, [blockName &#39;_adjust_fc&#39;]) batchNormalizationLayer(&#39;Name&#39;, [blockName &#39;_adjust_bn&#39;]) ]; shortcutOutput = [blockName &#39;_adjust_bn&#39;]; end % 添加层到网络 lgraph = addLayers(lgraph, mainLayers); lgraph = addLayers(lgraph, shortcutLayers); % 连接主路径 lgraph = connectLayers(lgraph, inputLayerName, [blockName &#39;_fc1&#39;]); % 连接跳跃路径 lgraph = connectLayers(lgraph, inputLayerName, shortcutLayers(1).Name); % 创建加法层 addLayer = additionLayer(2, &#39;Name&#39;, [blockName &#39;_add&#39;]); lgraph = addLayers(lgraph, addLayer); % 连接加法层输入 lgraph = connectLayers(lgraph, [blockName &#39;_bn2&#39;], [blockName &#39;_add/in1&#39;]); lgraph = connectLayers(lgraph, shortcutOutput, [blockName &#39;_add/in2&#39;]); % 添加输出激活函数 reluOut = reluLayer(&#39;Name&#39;, [blockName &#39;_out_relu&#39;]); lgraph = addLayers(lgraph, reluOut); lgraph = connectLayers(lgraph, [blockName &#39;_add&#39;], [blockName &#39;_out_relu&#39;]); end %% 步骤4: 模型训练 options = trainingOptions(&#39;adam&#39;, ... &#39;MaxEpochs&#39;, 50, ... &#39;MiniBatchSize&#39;, 64, ... &#39;ValidationData&#39;, {XTest, categorical(YTest)}, ... &#39;Plots&#39;, &#39;training-progress&#39;, ... &#39;InitialLearnRate&#39;, 0.001, ... &#39;LearnRateSchedule&#39;, &#39;piecewise&#39;, ... &#39;LearnRateDropFactor&#39;, 0.5, ... &#39;LearnRateDropPeriod&#39;, 10); net = trainNetwork(dsTrain, lgraph, options); %% 步骤5: 模型评估与残差分析 % 预测测试集 YPred = classify(net, XTest); % 计算准确率 accuracy = sum(YPred == categorical(YTest)) / numel(YTest); fprintf(&#39;测试集准确率: %.2f%%\n&#39;, accuracy*100); % 绘制残差图(回归任务参考) % residuals = double(YPred) - YTest; % 对于回归任务 % figure; % plot(residuals, &#39;o&#39;); % title(&#39;残差分布图&#39;); % xlabel(&#39;样本索引&#39;); % ylabel(&#39;残差值&#39;); % hold on; % plot(xlim, [0 0], &#39;r--&#39;); % 零参考线[^1] 该代码报错:错误使用 categorical (第 465 行) 无法基于密集分布的数值创建默认类别名称。请使用 CATEGORYNAMES 输入参数指定类别名称,或使用 DISCRETIZE。 出错 DNN (第 109 行) &#39;ValidationData&#39;, {XTest, categorical(YTest)}, ...
最新发布
08-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值