330二进制反码转换问题、267数组重排最小化差值——题目思路与知识点总结 | 豆包MarsCode AI刷题

118 阅读6分钟

330二进制反码转换问题、267数组重排最小化差值C++ | 豆包MarsCode AI刷题

330二进制反码转换问题

原问题

问题描述

小C在学习二进制运算,他了解到每个非负整数都有其二进制表示。例如,整数 5 可以被表示为二进制 "101",整数 11 可以被表示为二进制 "1011",并且除了 N = 0 外,任何二进制表示中都不含前导零。

二进制的反码表示是将每个 1 变为 0,每个 0 变为 1。例如,二进制数 "101" 的二进制反码为 "010"。现在小C想知道,给定一个十进制数 N,它的二进制反码对应的十进制数是多少。

测试样例

样例1:

输入:N = 5
输出:2

样例2:

输入:N = 10
输出:5

样例3:

输入:N = 0
输出:1

问题解构

具体要求

1、输入一个字符,将其转换成二进制表示,且不含前导零。

2、将二进制表示求反码

3、将反码转换成十进制数并输出

输入输出

输入:原字符

输出:转换后的字符

题目类型分析

考察进制转换,十进制转换成二进制,二进制转换成十进制,容易被忽略的点为转换成的二进制是不含前导零的。

思路

先将整数N转换成二进制字符串,再反转,再将反转后的字符串转换成十进制数并输出。

代码逻辑

一层逻辑

  • 将整数 N 转换为二进制字符串(不含前导零)
  • 反转二进制表示:将每个 '0' 替换为 '1',每个 '1' 替换为 '0'
  • 将反转后的二进制字符串转换回十进制数

二层逻辑

  • 将整数 N 转换为二进制字符串(不含前导零)
    • 定义二进制字符串
    • 当整数大于0时循环
      • N取余2如果等于0,拼接0,否则拼接1
      • N除以2
  • 反转二进制表示:将每个 '0' 替换为 '1',每个 '1' 替换为 '0'
    • 定义转换后的二进制字符串
    • 对二进制的每一个字符循环
      • 位等于0,拼接1,反之拼接0
  • 将反转后的二进制字符串转换回十进制数
    • 定义int类型结果
    • 定义原始次方数为0
    • 倒序遍历字符串
      • 如果字符为1,则左移一位后加入结果
      • 次方数加一

代码

#include <iostream>
#include <string>

using namespace std;

int solution(int N) {
    // write code here
    // 特殊情况:如果 N 为 0,直接返回 0
    if (N == 0) {
        return 1;
    }

    // 将整数 N 转换为二进制字符串(不含前导零)
    string binary = "";
    while (N > 0) {
        binary = (N % 2 == 0 ? "0" : "1") + binary;
        N /= 2;
    }

    // 反转二进制表示:将每个 '0' 替换为 '1',每个 '1' 替换为 '0'
    string onesComplement = "";
    for (char bit : binary) {
        onesComplement += (bit == '0' ? '1' : '0');
    }

    // 将反转后的二进制字符串转换回十进制数
    int result = 0;
    int power = 0;
    for (int i = onesComplement.length() - 1; i >= 0; --i) {
        if (onesComplement[i] == '1') {
            result += (1 << power);
        }
        power++;
    }

    return result;
}

int main() {
    std::cout << (solution(5) == 2) << std::endl;
    std::cout << (solution(10) == 5) << std::endl;
    std::cout << (solution(0) == 1) << std::endl;
    return 0;
}

267数组重排最小化差值

原问题

问题描述

小C 和小U 有两个数组,分别是 a 和 b,它们的长度相同。小U 想通过重新排列数组 a 的元素,来最小化 a 和 b 之间的差异。具体来说,他们要最小化所有元素差值绝对值之和,即 sum(abs(a[i] - b[i]))
你能帮助小C 和小U 找到这个最小化的值吗?

测试样例

样例1:

输入:a = [2, 1, 3, 2], b = [5, 2, 4, 2]
输出:5

样例2:

输入:a = [1, 4, 6], b = [2, 5, 7]
输出:3

样例3:

输入:a = [1, 9, 6], b = [2, 5, 7]
输出:4

问题解构

具体要求

给定两个数组A和B,重新排列A数组的元素顺序,最小化所有元素差值绝对值之和,即 sum(abs(a[i] - b[i])),求这个最小化的值。

输入输出

输入:数组A和数组B

输出:int类型的值

题目类型分析

数学类问题

思路

注意因为只求最小化的值,所以A和B其实可以都重新排列元素(B不排列和B也排列两种情况不影响最终求的结果),而最小化绝对差值和的关键是尽量让相近的数字对齐。所以,可以把它们均从小到大排列,此时数字尽可能对齐了。

代码逻辑

一层逻辑

  • 排序数组A和B
  • 计算最小化差值之和

二层逻辑

  • 排序数组A和B
    • 利用sort函数分别排序A和B数组
  • 计算最小化差值之和
    • 遍历A和B中的元素,计算差值并相加

代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>  // for abs
#include <string>

using namespace std;
// !思路:因为只求最小的差值和,所以b数组的顺序无所谓,
// 因此,可以b数组排序后,再求结果也不会变化
// 最小化绝对差值和的关键是尽量让相近的数字对齐
long long solution(vector<int> a, vector<int> b) {
    // write code here
    // 排序数组 a 和 b
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());

    // 计算最小化差值之和
    long long sum = 0;
    for (int i = 0; i < a.size(); ++i) {
        sum += abs(a[i] - b[i]);
    }
    return sum;
}

int main() {
    vector<int> a1 = {2, 1, 3, 2}, b1 = {5, 2, 4, 2};
    vector<int> a2 = {1, 4, 6}, b2 = {2, 5, 7};
    vector<int> a3 = {1, 9, 6}, b3 = {2, 5, 7};
    
    cout << (solution(a1, b1) == 5) << endl;
    cout << (solution(a2, b2) == 3) << endl;
    cout << (solution(a3, b3) == 4) << endl;
    
    return 0;
}

代码涉及知识的解释

sort函数

在 C++ 中,sort 函数是用于对容器中的元素进行排序的标准库函数。它位于 C++ 标准库中的 <algorithm> 头文件中,可以用于排序不同类型的容器(如数组、vectordeque 等)。默认情况下,sort 会根据元素的大小进行升序排序,但也可以通过自定义比较函数来实现降序或根据其他标准进行排序。

基本语法

cpp
复制代码
#include <algorithm>  // 包含 sort 函数
#include <vector>     // 包含 vector 容器
#include <iostream>   // 用于输入输出流

// 默认排序:升序
std::sort(开始迭代器, 结束迭代器);

// 使用自定义比较函数排序(例如降序)
std::sort(开始迭代器, 结束迭代器, 比较函数);
  • 开始迭代器:指向排序范围的第一个元素。
  • 结束迭代器:指向排序范围之后的一个元素(即不包含该元素)。
  • 比较函数:一个自定义的二元函数(或函数对象),用于定义元素排序的规则。