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

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

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

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

网友回帖我也瞄了下,有人劝他赶紧分,别耽误姑娘的青春;也有人说挣钱多是你能力,但拿收入当显微镜去挑伴侣,那就有点寒碜了。我比较认同后面这种。

怎么说呢,两个人收入差距大不稀奇,关键是你把对象当“人生伙伴”,还是当“理财产品”。婚姻又不是并购案,不是看谁报表好就收谁。今天你赚140万,万一哪天跌到40万呢?如果此刻你因为她挣得少就“越看越不顺眼”,说明问题已经不是钱,而是你根本不够尊重她。

算法题:最接近的三数之和

今天下班路上在地铁上刷题,看到一个老生常谈的题,手机都差点没抓稳:最接近的三数之和。想着平时群里一堆小伙伴问这个题咋写,不如就用一篇文章讲清楚,顺手用 Ruby 写一版,比较少人用 Ruby 刷题,你们正好抄个作业。

意思特别简单:给你一个整数数组 nums,再给你一个目标值 target,让你从 nums 里随便挑三个数出来,相加以后,结果要尽量接近 target,最后把这个“最接近的和”返回。

比如:nums = [-1, 2, 1, -4], target = 1所有三数和里:

  • -1 + 2 + 1 = 2
  • -1 + 2 + (-4) = -3
  • -1 + 1 + (-4) = -4
  • 2 + 1 + (-4) = -1

离 1 最近的是 2,所以答案就是 2。

看着是不是很“无脑”?但真要你写个高效的,很多人一上来就翻车。

最直观的思路就是: 三重循环,枚举所有三元组 (i, j, k),把和算出来,跟 target 比一比谁更近,一路更新答案。

伪代码脑补一下就是:

  • 第一层选第一个数
  • 第二层选第二个数
  • 第三层选第三个数
  • 算和、更新最优

时间复杂度是啥?O(n^3)。 数组一长,直接原地爆炸。面试官可能会点点头:“会是会,但不能用”。

所以我们得动点脑子,把三重循环打薄一点。

你想啊,如果数组是有序的,事情就好办很多了。

整体思路是这样的:

  1. 先把 nums 排个序,这个是 O(n log n)。
  2. 然后固定一个下标 i,相当于先选好第一个数。
  3. 剩下两个数就从 i+1 和 nums.length-1 开始,用左右指针往中间夹。

为啥能这么干?因为数组有序了:

  • 设当前三个数的和叫 sum
  • 如果 sum 比 target 小,那你想让它更接近 target,是不是应该把和变大一点? 有序数组里,变大最简单的方式,就是把左指针往右挪一格。
  • 如果 sum 比 target 大,那就把右指针往左挪,让和变小。

在这个过程中,我们一直维护一个“目前最接近的和”,每次算出新的 sum,就拿 |sum - target| 跟之前的最小差值比一比,小就更新。

如果有一次刚好 sum == target,那就不用算了,直接可以返回 target,再怎么折腾都不可能比它更近了。

时间复杂度变成 O(n^2): 外层固定 i 是 O(n),内层双指针跑一遍又是 O(n)。

直接上代码,你可以本地随便跑跑:

defthree_sum_closest(nums, target)# 至少要有三个数returnnilif nums.length < 3# 排序,方便用双指针  nums.sort!# 先随便取一个合法的三数和当初始值  best_sum = nums[0] + nums[1] + nums[2]  (0..(nums.length - 3)).each do|i|    left  = i + 1    right = nums.length - 1while left < right      current_sum = nums[i] + nums[left] + nums[right]# 如果更接近目标,就更新if (current_sum - target).abs < (best_sum - target).abs        best_sum = current_sumend# 刚好等于 target,直接返回,没比这更近的了if current_sum == targetreturn current_sumelsif current_sum < target# 和太小了,让它大一点        left += 1else# 和太大了,让它小一点        right -= 1endendend  best_sumend# 小测试nums   = [-1, 2, 1, -4]target = 1puts three_sum_closest(nums, target)  # 输出 2

这个版本算是比较“面试友好”的写法:

  • 没搞什么奇怪的抽象
  • 逻辑顺、变量名也还算说人话
  • Ruby 本身整数不会溢出,你也不用操心大数问题

稍微带你脑补一轮运行过程

就以 [-1, 2, 1, -4] 为例:

  1. 排序之后是 [-4, -1, 1, 2]

  2. 第一次 i = 0,选的是 -4

    • left = 1(-1),right = 3(2)
    • sum = -4 + (-1) + 2 = -3,比 target = 1 小 想变大一点,left++ → 指向 1
    • 这次 sum = -4 + 1 + 2 = -1,还是小于 1,再 left++
    • left 跑到 right 了,这一轮结束
  3. 第二次 i = 1,选的是 -1

    • left = 2(1),right = 3(2)
    • sum = -1 + 1 + 2 = 2,这个跟 1 的距离是 1
    • 目前为止最接近的就是 2 了

后面再怎么跑,也不会出现比 2 更接近 1 的结果了,所以最终答案就是 2。

随手提醒几个坑,免得你写题的时候被卡住:

  • 初始值别设成什么 Float::INFINITY 之类的,直接取前三个数的和更自然,也能保证是一个真的三数和。
  • 数组长度小于 3,我这里直接返回 nil,实际项目里你可以抛异常或者自己约定个行为。
  • 如果数组里有重复数字,其实完全不用特意去重,因为题目只是让你“选三个位置”,而不是要求三数必须互不相同的值,只要下标不一样就行。

这个“三数最接近”算是那种:一眼看上去简单、但想写得又快又优雅,还得理解一点“排序 + 双指针”套路的题。 你要是把这个思路吃透了,3Sum、四数之和、甚至更一般的 k-sum,套路都差不多,就是多一层递归而已。

有空你可以把上面这段 Ruby 代码自己手敲一遍,改几个测试数据看看输出对不对,比只看讲解强太多。哪一步不太顺的,直接拿具体例子在纸上跑一遍,脑子就通了。

🔥编程资料合集🔥

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

最新文章

随机文章