丢失的第一个整数

给出一个无序的正数数组,找出其中没有出现的最小正整数。
样例
如果给出 [1,2,0], return 3
如果给出 [3,4,-1,1], return 2

使用位图解决

用位图来标记所有出现过的整数,遍历位图找出第一个没出现的正整数就行了.
缺点是,需要使用的空间大小是非常数的,无法直接估计,因此位图的创建本身就不适合.

排序解决

思路:交换数组元素,使得数组中第i位存放数值(i+1)。最后遍历数组,寻找第一个不符合此要求的元素,返回其下标。整个过程需要遍历两次数组,复杂度为O(n)。
这里写图片描述

public class Solution {
    /**    
     * @param A: an array of integers
     * @return: an integer
     */
    public int firstMissingPositive(int[] A) {
        // write your code here    
        if(A.length==0||A==null)
            return 1;
        //把元素放入正确的位置,例如1放在A[0],2放在A[1]...
        for(int i = 0;i<A.length;i++)
        {
            while(A[i]!=i+1)
            {
                if(A[i]>=A.length||A[i]<=0||A[i]==A[A[i]-1])
                    break;
                int temp = A[i];
                A[i] = A[temp-1];
                A[temp-1] = temp;
            }
        }

        for(int i = 0;i<A.length;i++)
        {
            if(A[i]!=i+1)
                return i+1;
        }
        return A.length+1;
        //有缺陷的方法
        // int []intMap = new int[100];

        // for(int i = 0; i < A.length; i++)
        // {
        //     if(A[i] > 0 && A[i] < 100)
        //         intMap[A[i]] = 1;
        // }
        // int i = 1;
        // for(; i < 100; i++)
        // {
        //     if(intMap[i] == 0)
        //         break;
        // }

        // return i;
    }
}
<think>我们面对的问题是如何将数据(一个4字节整数值和一个逻辑值)打包并通过串口发送。这里我们使用C/C++(Arduino)和Python(PC端)两种语言分别实现。 ### 数据包设计 假设我们要发送的数据包包含: - 一个逻辑值(布尔值,1字节) - 一个4字节整数值(大端或小端格式,这里我们选择小端格式) 数据包结构: | 包头 (1字节) | 逻辑值 (1字节) | 整数值 (4字节) | 包尾 (1字节) | |--------------|---------------|---------------|-------------| | 0xA5 | 0x01或0x00 | 低字节在前 | 0x5A | 总长度:1+1+4+1=7字节。 ### 方案1:Arduino(C++)作为发送端 在Arduino上,我们将逻辑值和整数值打包成数据包,通过串口发送。 ```cpp // Arduino发送端代码 void setup() { Serial.begin(9600); // 初始化串口,波特率9600 } void loop() { bool logicValue = true; // 逻辑值,可以动态改变 int32_t intValue = 123456789; // 4字节整数值 // 构建数据包 (7字节) uint8_t packet[7] = {0}; packet[0] = 0xA5; // 包头 packet[1] = logicValue ? 0x01 : 0x00; // 逻辑值 // 整数值按小端格式放入(低字节在前) packet[2] = (uint8_t)(intValue & 0xFF); packet[3] = (uint8_t)((intValue >> 8) & 0xFF); packet[4] = (uint8_t)((intValue >> 16) & 0xFF); packet[5] = (uint8_t)((intValue >> 24) & 0xFF); packet[6] = 0x5A; // 包尾 // 发送数据包 Serial.write(packet, 7); delay(1000); // 每秒发送一次 } ``` ### 方案2:Python作为发送端 在Python中,我们可以使用`pyserial`库来发送串口数据。同样,我们将数据打包成7字节的数据包。 ```python import serial import time # 配置串口 ser = serial.Serial('COM3', 9600) # 根据实际情况修改串口号 try: while True: logic_value = True # 逻辑值 int_value = 123456789 # 整数值 # 构建数据包 packet = bytearray() packet.append(0xA5) # 包头 packet.append(0x01 if logic_value else 0x00) # 逻辑值 # 整数值按小端格式(低字节在前) packet.append((int_value >> 0) & 0xFF) # 最低字节 packet.append((int_value >> 8) & 0xFF) packet.append((int_value >> 16) & 0xFF) packet.append((int_value >> 24) & 0xFF) # 最高字节 packet.append(0x5A) # 包尾 # 发送数据包 ser.write(packet) time.sleep(1) # 每秒发送一次 except KeyboardInterrupt: ser.close() ``` ### 接收端处理(Arduino或Python) 接收端需要按照相同的协议解析数据包。这里以Arduino作为接收端为例: ```cpp // Arduino接收端代码 const int PACKET_SIZE = 7; uint8_t packetBuffer[PACKET_SIZE]; int bufferIndex = 0; void setup() { Serial.begin(9600); } void loop() { if (Serial.available()) { uint8_t incomingByte = Serial.read(); // 检查包头 if (bufferIndex == 0 && incomingByte == 0xA5) { packetBuffer[bufferIndex++] = incomingByte; } else if (bufferIndex > 0 && bufferIndex < PACKET_SIZE-1) { packetBuffer[bufferIndex++] = incomingByte; } else if (bufferIndex == PACKET_SIZE-1 && incomingByte == 0x5A) { packetBuffer[bufferIndex] = incomingByte; // 解析数据包 bool logicValue = packetBuffer[1] != 0; int32_t intValue = (packetBuffer[2] << 0) | (packetBuffer[3] << 8) | (packetBuffer[4] << 16) | (packetBuffer[5] << 24); // 打印解析结果 Serial.print("逻辑值: "); Serial.print(logicValue ? "TRUE" : "FALSE"); Serial.print(" | 整数值: "); Serial.println(intValue); bufferIndex = 0; // 重置缓冲区 } else { bufferIndex = 0; // 错误,重置 } } } ``` ### 注意事项 1. **字节顺序**:我们使用了小端格式(低字节在前),如果接收端是大端系统,需要调整顺序。 2. **数据包边界**:使用包头包尾来界定数据包,避免粘包问题。 3. **错误处理**:实际应用中可添加校验和(例如异或校验)提高可靠性。 ### 扩展:添加校验和 在数据包中增加校验和(1字节),放在包尾之前: 包头(1) | 逻辑值(1) | 整数值(4) | 校验和(1) | 包尾(1) → 总长度8字节。 发送端计算校验和(例如所有数据字节异或): ```cpp // 发送端计算校验和(从逻辑值到整数值的4个字节) uint8_t checksum = packet[1]; for (int i=2; i<=5; i++) { checksum ^= packet[i]; } packet[6] = checksum; // 校验和放在第6位(0开始索引) packet[7] = 0x5A; // 包尾 ``` 接收端验证校验和。 ### 总结 以上代码实现了将逻辑值和4字节整数值打包发送的功能。发送端可以是Arduino或Python,接收端同样可以是两者之一。关键在于数据包格式的定义和解析的一致性。 §§相关问题§§ 1. 如何修改数据包结构以包含多个不同类型的数据? 2. 在串口通信中如何处理数据包丢失或损坏的问题? 3. 如何提高串口通信的传输速率和可靠性?</think>### 完整实现:打包并发送逻辑值和4字节整数值 下面提供C/C++和Python两种实现方案,用于将逻辑值(布尔值)和4字节整数值打包并通过串口发送。 --- ### C/C++实现 (Arduino平台) ```cpp #include <Arduino.h> // 数据包结构定义 struct DataPacket { uint8_t header = 0xA5; // 包头标识 (1字节) bool logicValue; // 逻辑值 (1字节) uint32_t intValue; // 4字节整数值 uint8_t footer = 0x5A; // 包尾标识 (1字节) }; void setup() { Serial.begin(9600); // 初始化串口通信 while (!Serial); // 等待串口连接 } void loop() { // 创建数据包实例 DataPacket packet; // 设置数据值 (可替换为实际数据) packet.logicValue = true; // 逻辑值 packet.intValue = 0x12345678; // 4字节整数值 // 发送数据包 Serial.write((const uint8_t*)&packet, sizeof(DataPacket)); // 可选:调试输出 Serial.print("\n发送数据: "); Serial.print(packet.logicValue ? "TRUE" : "FALSE"); Serial.print(", 0x"); Serial.println(packet.intValue, HEX); delay(1000); // 每秒发送一次 } ``` #### 关键说明: 1. **数据包结构**:包头(0xA5) + 逻辑值(1字节) + 整数值(4字节) + 包尾(0x5A) 2. **内存布局**: - 总大小:1+1+4+1=7字节 - 使用`uint32_t`确保4字节整型 3. **发送方式**: - `Serial.write()`直接发送内存块 - 使用指针转换`(const uint8_t*)&packet` --- ### Python实现 (使用pyserial) ```python import serial import struct import time # 配置串口 (根据实际修改端口和波特率) ser = serial.Serial('COM3', 9600, timeout=1) def send_packet(logic_value, int_value): """打包并发送数据包""" # 定义数据包格式: 包头(1B) + 逻辑值(1B) + 整数值(4B) + 包尾(1B) packet_format = '<B ? I B' # <表示小端字节序 # 打包数据 packet = struct.pack( packet_format, 0xA5, # 包头 logic_value, # 逻辑值 int_value, # 4字节整数 0x5A # 包尾 ) # 发送数据 ser.write(packet) print(f"发送数据: {logic_value}, 0x{int_value:08X}") # 示例使用 try: while True: send_packet(True, 0x12345678) # 发送测试数据 time.sleep(1) except KeyboardInterrupt: ser.close() ``` #### 关键说明: 1. **数据打包**: - 使用`struct.pack()`进行二进制打包 - 格式字符串`'<B ? I B'`含义: - `<`:小端字节序 - `B`:无符号字节 (包头) - `?`:布尔值 (逻辑值) - `I`:4字节无符号整数 - `B`:无符号字节 (包尾) 2. **字节序处理**: - 小端格式(`<`):低位字节在前 - 大端格式(`>`):高位字节在前 (根据接收端要求调整) --- ### 数据包格式详解 | 偏移量 | 长度 | 内容 | 值类型 | 说明 | |--------|------|-----------|----------|--------------------| | 0 | 1 | 0xA5 | uint8_t | 包头标识 | | 1 | 1 | 0x00/0x01 | bool | 逻辑值 (false/true)| | 2 | 4 | 0xXXXXXXXX| uint32_t | 4字节整数值 | | 6 | 1 | 0x5A | uint8_t | 包尾标识 | #### 字节序说明: - **小端格式**:低位字节在前 (如`0x12345678`发送顺序: `0x78 0x56 0x34 0x12`) - **大端格式**:高位字节在前 (如`0x12345678`发送顺序: `0x12 0x34 0x56 0x78`) --- ### 接收端处理建议 在接收端(如PC程序或另一个微控制器),需按相同格式解析: ```cpp // Arduino接收示例 struct DataPacket { uint8_t header; bool logicValue; uint32_t intValue; uint8_t footer; }; void loop() { if (Serial.available() >= sizeof(DataPacket)) { DataPacket packet; Serial.readBytes((uint8_t*)&packet, sizeof(packet)); if (packet.header == 0xA5 && packet.footer == 0x5A) { Serial.print("收到: "); Serial.print(packet.logicValue ? "TRUE" : "FALSE"); Serial.print(", 0x"); Serial.println(packet.intValue, HEX); } } } ``` --- ### 注意事项 1. **字节序一致性**:发送端和接收端必须使用相同字节序 2. **数据对齐**:结构体可能存在内存对齐问题,使用`#pragma pack(1)`(C/C++)或`struct.pack`(Python)避免 3. **错误处理**:添加校验和增强可靠性 ```cpp // C/C++添加校验和 uint8_t checksum = packet.logicValue; for (int i = 0; i < 4; i++) { checksum ^= ((uint8_t*)&packet.intValue)[i]; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值