当前位置:首页>女朋友>我一年140万 女朋友一年15万 差了快10倍了 要不要换一个?感觉差距会越来越大 还没结婚越看越不顺眼了 谈了才两年

我一年140万 女朋友一年15万 差了快10倍了 要不要换一个?感觉差距会越来越大 还没结婚越看越不顺眼了 谈了才两年

  • 2026-10-13 08:58:40
我一年140万 女朋友一年15万 差了快10倍了 要不要换一个?感觉差距会越来越大 还没结婚越看越不顺眼了 谈了才两年

刚看到个贴子,说男生一年140万,女朋友一年15万,差了快10倍,谈了两年,越看越不顺眼,纠结要不要换一个。

我觉得这事吧,关键不在钱多少,而在你到底想要什么样的关系。你要的是“合作伙伴”,那确实会在意对方有没有共同承担生活的能力;你要的是“照顾与被照顾”,那收入差距就不是核心矛盾。怕的就是嘴上说不介意,心里天天拿工资单当显微镜。

换个角度想,现在嫌弃她15万,以后可能也会嫌弃别人30万、50万,“不顺眼”的借口永远能找到。说到底还是价值观问题:你是把伴侣当资产配置,还是当一起过日子的人

今日算法题

想象下,你有一堆整数,像是一桌子乱七八糟的账单,然后老板说: “从里面随便挑三个,加起来要尽量接近 target,看你能凑到多少。”

这就是算法题「最接近的三数之和」:

给定整数数组 nums 和目标值 target,从中选出三个数,使它们的和最接近 target。 返回这个最接近的和(保证答案唯一)。

Go 版本函数一般长这样:

functhreeSumClosest(nums []int, target int)int

我们要做的,就是把这个函数实现好。

最粗暴的办法其实也挺好理解: 三个数,对吧,那就三重循环,把所有 i < j < k 的组合都试一遍:

  • 算它们的和 sum
  • 和 target 做差,看离得多近
  • 记一个“当前最优”的 sum

伪代码感觉就是:

best := 很大的值for ifor jfor k      sum := nums[i] + nums[j] + nums[k]      如果比当前 best 更接近 target,就更新 best

问题也很明显:时间复杂度是 O(n^3),数组一大,直接卡死,线上绝对不敢这么写。

常规思路是这样的:

  1. 先把数组排序
  2. 固定第一个数 nums[i]
  3. 剩下的两数,用「左右指针」往中间逼近

为啥排序之后好办? 因为排完序,数组是单调递增的,你就能通过比较当前和与 target 的大小,来决定是让左指针右移,还是右指针左移,从而让和变大或变小——这个在 Go 里很好写。

整个过程大概是:

  • 对 nums 升序排序

  • 初始化一个 bestSum 为任意一个合法的三数和(比如前 3 个相加),顺便记一个 minDiff,表示和 target 的最小差值

  • 从 i = 0 遍历到 len(nums)-3,每次:

    • 设 left := i+1,right := len(nums)-1
    • 当前和 sum := nums[i] + nums[left] + nums[right]
    • 如果 |sum - target| 更小,就更新 bestSum 和 minDiff
    • 如果 sum == target,那就直接可以返回了,因为不可能比这个更近
    • 如果 sum < target,说明和太小了,让 left++
    • 如果 sum > target,说明和太大了,让 right--

时间复杂度就变成了:外层 O(n),内层双指针 O(n),合起来 O(n^2),这个在面试题里非常能打。

直接上 Go 源码,能复制就跑的那种:

package mainimport ("fmt""math""sort")functhreeSumClosest(nums []int, target int)int { n := len(nums)if n < 3 {// 正常 LeetCode 里不会给这种输入,这里简单兜个底panic("nums length must be at least 3") }// 先排序 sort.Ints(nums)// 初始化:随便取一个合法三元组当初始答案 bestSum := nums[0] + nums[1] + nums[2] minDiff := int(math.Abs(float64(bestSum - target)))for i := 0; i < n-2; i++ {  left, right := i+1, n-1for left < right {   sum := nums[i] + nums[left] + nums[right]   diff := int(math.Abs(float64(sum - target)))if diff < minDiff {    minDiff = diff    bestSum = sum   }if sum == target {// 已经是最理想的情况了return sum   } elseif sum < target {// 和偏小,左指针右移,试图让和变大    left++   } else {// 和偏大,右指针左移,试图让和变小    right--   }  } }return bestSum}funcmain() { nums := []int{-1, 2, 1, -4} target := 1 fmt.Println(threeSumClosest(nums, target)) // 输出 2,因为 -1 + 2 + 1 = 2}

可以注意几个小细节:

  • minDiff 用的是 math.Abs,但 math.Abs 的参数是 float64,所以要转来转去一圈
  • 初始化 bestSum 用的是 nums[0] + nums[1] + nums[2],这样一来后面就不需要写「这是第一轮,先赋值」这种分支
  • 我没有专门去「跳过重复元素」,因为这是「最接近的和」,不是求去重的三元组,重复其实无伤大雅,逻辑更简单

就这样,这题搞定,你可以先自己敲一遍,顺手多打几个不同的 nums 和 target 试试,感觉一下双指针怎么在数组里“滑”起来的。

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《GO后端开发资料合集》。总量高达650GB。

最新文章

随机文章