男的急啥呢,房子还没影儿呢,分手倒先挂嘴边了。
女生工作稳定、有能力在婚前自己买套三房,甚至还打算拿它当婚房,这搁大多数人眼里不都挺靠谱的嘛。结果男朋友不高兴了,非要两个人一起买,说要弄个更大、更好的。听着像规划未来,可仔细品品又有点不对味儿。
你想一起买,那可以谈预算、聊城市、算贷款压力——哪怕说一句“我也想参与这个家”,都挺正常。但一上来就是“你买我就分手”,这味道立马就变了,跟抢方向盘似的。
房子是资产,也是底气。尤其是婚前靠自己买的,不偷不抢不啃老,凭什么先被吓一跳。真要打算结婚,那该是两个人一块儿把日子过稳,而不是先把对方的选择权按死。要我看,先别急着选房还是选人,先瞅瞅这个人到底是在想共同生活,还是怕你太有退路。
算法题:输出比赛匹配对
比赛对阵表这题,最容易写歪的地方不是括号,而是轮次。
输入 n = 8,队伍编号从 1 到 8,实力已经排好序。第一名打第八名,第二名打第七名,这个没啥好争的。麻烦在下一轮:上一轮生成的匹配结果,本身又要继续被当成一个“队伍”参与配对。
比如第一轮是这样:
(1,8)
(2,7)
(3,6)
(4,5)
下一轮不是随便拼,而是继续头尾匹配:
((1,8),(4,5))
((2,7),(3,6))
最后得到:
(((1,8),(4,5)),((2,7),(3,6)))
这块儿我一般不先想递归。递归当然能做,但这题的数据推进很直——像一排人站队,每轮把最左和最右拉出来打一场,然后形成新的一排。用数组模拟反而不容易出错。
代码可以这么写:
class Solution {
public String findContestMatch(int n) {
String[] round = new String[n];
for (int i = 0; i < n; i++) {
round[i] = String.valueOf(i + 1);
}
int size = n;
while (size > 1) {
String[] next = new String[size / 2];
int left = 0;
int right = size - 1;
int idx = 0;
while (left < right) {
next[idx++] = "(" + round[left] + "," + round[right] + ")";
left++;
right--;
}
round = next;
size = next.length;
}
return round[0];
}
}
不需要在这儿硬塞一堆数学推导。你盯住 round 这个数组就行——它每一轮表示“当前还在比赛里的位置”。
第一次:
round = ["1","2","3","4","5","6","7","8"]
配完以后变成:
round = ["(1,8)","(2,7)","(3,6)","(4,5)"]
再配一次:
round = ["((1,8),(4,5))","((2,7),(3,6))"]
最后剩一个,就是答案。
这里有个小坑:别把 n 当成固定长度一路用到底。每打一轮,队伍数量都会减半,所以循环里得维护一个当前长度 size。如果还用原来的 n 去扫数组,后面要么越界,要么拼出来一堆空值。
这道 LeetCode 题还有另一种写法,用 List<String> 会更顺手,尤其是面试现场写代码时,能少处理数组长度。
import java.util.ArrayList;
import java.util.List;
class Solution {
public String findContestMatch(int n) {
List<String> teams = new ArrayList<>();
for (int id = 1; id <= n; id++) {
teams.add(String.valueOf(id));
}
while (teams.size() > 1) {
List<String> nextRound = new ArrayList<>();
int l = 0;
int r = teams.size() - 1;
while (l < r) {
String match = "(" + teams.get(l) + "," + teams.get(r) + ")";
nextRound.add(match);
l++;
r--;
}
teams = nextRound;
}
return teams.get(0);
}
}
我更喜欢第二种,代码读起来像真实比赛推进:本轮队伍进来,配完生成下一轮。没有额外状态,也不用猜某个下标到底属于第几轮。
复杂度也挺干净。每一轮都要处理当前所有队伍的一半,整体看下来每个编号都会被拼进字符串里,括号和逗号也会不断增加,所以时间主要花在字符串构造上。按算法题的口径,可以认为模拟轮次是 O(n log n) 级别;空间就是保存每轮结果,O(n)。
这题别想复杂。它不是让你算冠军,也不是让你真的模拟胜负,它只是让你按规则把对阵表打印出来。头尾配对,生成下一轮,直到只剩一个字符串,停在这儿就够了。
如果你也有类似的生活困惑或者算法题解,欢迎到云栈社区 一起聊聊。