|
| 1 | +--- |
| 2 | +title: 2578.最小和分割 |
| 3 | +date: 2023-10-09 09:13:42 |
| 4 | +tags: [题解, LeetCode, 简单, 贪心, 数学, 排序] |
| 5 | +--- |
| 6 | + |
| 7 | +# 【LetMeFly】2578.最小和分割:贪心(数学) |
| 8 | + |
| 9 | +力扣题目链接:[https://leetcode.cn/problems/split-with-minimum-sum/](https://leetcode.cn/problems/split-with-minimum-sum/) |
| 10 | + |
| 11 | +<p>给你一个正整数 <code>num</code> ,请你将它分割成两个非负整数 <code>num1</code> 和 <code>num2</code> ,满足:</p> |
| 12 | + |
| 13 | +<ul> |
| 14 | + <li><code>num1</code> 和 <code>num2</code> 直接连起来,得到 <code>num</code> 各数位的一个排列。 |
| 15 | + |
| 16 | + <ul> |
| 17 | + <li>换句话说,<code>num1</code> 和 <code>num2</code> 中所有数字出现的次数之和等于 <code>num</code> 中所有数字出现的次数。</li> |
| 18 | + </ul> |
| 19 | + </li> |
| 20 | + <li><code>num1</code> 和 <code>num2</code> 可以包含前导 0 。</li> |
| 21 | +</ul> |
| 22 | + |
| 23 | +<p>请你返回 <code>num1</code> 和 <code>num2</code> 可以得到的和的 <strong>最小</strong> 值。</p> |
| 24 | + |
| 25 | +<p><strong>注意:</strong></p> |
| 26 | + |
| 27 | +<ul> |
| 28 | + <li><code>num</code> 保证没有前导 0 。</li> |
| 29 | + <li><code>num1</code> 和 <code>num2</code> 中数位顺序可以与 <code>num</code> 中数位顺序不同。</li> |
| 30 | +</ul> |
| 31 | + |
| 32 | +<p> </p> |
| 33 | + |
| 34 | +<p><strong>示例 1:</strong></p> |
| 35 | + |
| 36 | +<pre> |
| 37 | +<b>输入:</b>num = 4325 |
| 38 | +<b>输出:</b>59 |
| 39 | +<b>解释:</b>我们可以将 4325 分割成 <code>num1 </code>= 24 和 num2<code> = </code>35 ,和为 59 ,59 是最小和。 |
| 40 | +</pre> |
| 41 | + |
| 42 | +<p><strong>示例 2:</strong></p> |
| 43 | + |
| 44 | +<pre> |
| 45 | +<b>输入:</b>num = 687 |
| 46 | +<b>输出:</b>75 |
| 47 | +<b>解释:</b>我们可以将 687 分割成 <code>num1</code> = 68 和 <code>num2 </code>= 7 ,和为最优值 75 。 |
| 48 | +</pre> |
| 49 | + |
| 50 | +<p> </p> |
| 51 | + |
| 52 | +<p><strong>提示:</strong></p> |
| 53 | + |
| 54 | +<ul> |
| 55 | + <li><code>10 <= num <= 10<sup>9</sup></code></li> |
| 56 | +</ul> |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | +## 方法一:贪心(数学) |
| 61 | + |
| 62 | +先说结论:将给定数字转为字符串后将其中字符从小到大排序,然后依次分配给两个新数字即可。 |
| 63 | + |
| 64 | +不严谨的原理描述: |
| 65 | + |
| 66 | ++ 越高位数字尽量越小,因此要从小到大排序 |
| 67 | ++ 最终返回的是两数之和,所以首先位数越小越好,因此尽可能两个数字长度相等 |
| 68 | ++ 若两个数长度不相等,更长的那个数字的最高位要尽可能小(例如将```23456```分成```246```和```35```,唯一的百位是最小的```2```) |
| 69 | + |
| 70 | +结论中描述的分法恰好满足。 |
| 71 | + |
| 72 | ++ 时间复杂度$O(k\log k)$,其中$k = \log num$ |
| 73 | ++ 空间复杂度$O(\log k)$ |
| 74 | + |
| 75 | +### AC代码 |
| 76 | + |
| 77 | +#### C++ |
| 78 | + |
| 79 | +```cpp |
| 80 | +class Solution { |
| 81 | +public: |
| 82 | + int splitNum(int num) { |
| 83 | + string s = to_string(num); |
| 84 | + sort(s.begin(), s.end()); |
| 85 | + string n1, n2; |
| 86 | + for (int i = 0; i < s.size(); i++) { |
| 87 | + (i % 2 ? n2 : n1) += s[i]; |
| 88 | + } |
| 89 | + // cout << "n1: " << n1 << ", n2: " << n2 << endl; //********** |
| 90 | + return atoi(n1.c_str()) + atoi(n2.c_str()); |
| 91 | + } |
| 92 | +}; |
| 93 | +``` |
| 94 | +
|
| 95 | +#### Python |
| 96 | +
|
| 97 | +```python |
| 98 | +class Solution: |
| 99 | + def splitNum(self, num: int) -> int: |
| 100 | + s = sorted(str(num)) |
| 101 | + n = ['', ''] |
| 102 | + for i in range(len(s)): |
| 103 | + n[i % 2] += s[i] |
| 104 | + return int(n[0]) + int(n[1]) |
| 105 | +``` |
| 106 | + |
| 107 | +> 同步发文于CSDN,原创不易,转载经作者同意后请附上[原文链接](https://blog.tisfy.eu.org/2023/10/09/LeetCode%202578.%E6%9C%80%E5%B0%8F%E5%92%8C%E5%88%86%E5%89%B2/)哦~ |
| 108 | +> Tisfy:[https://letmefly.blog.csdn.net/article/details/133694187](https://letmefly.blog.csdn.net/article/details/133694187) |
0 commit comments