LC.496 | 下一个更大元素Ⅰ | 栈 | 单调栈/map

输入:

  • 一个数组 nums1

  • 一个数组 nums2

  • 约束nums1nums2 的子集,且两个数组都没有重复元素。

要求:

  • 遍历 nums1 中的每一个元素 x

  • nums2 中找到 x 的位置。

  • 从该位置开始向查找,找出第一个x 大的数

输出:

  • 一个与 nums1 等长的答案数组 ans

  • ans[i] 对应 nums1[i] 找到的“下一个更大元素”。

  • 如果找不到,则存入 -1


思路:遍历一次 nums2,计算出 nums2所有元素的“下一个更大元素”是谁,并把这个 {值 -> 答案} 的关系存入一个哈希表。最后再遍历 nums1,去哈希表里查答案就行了。


复杂度:

        时间复杂度:O(N+M) 遍历nums1 和 nums2

        空间复杂度:O(M) nums2的大小为基准


class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        stack<int> t1; // 存索引
        unordered_map<int, int> t2;
        for (int i = 0; i < nums2.size(); i++) {
            t2[nums2[i]] = -1;
        }

        for (int i = 0; i < nums2.size(); i++) {
            if (!t1.empty() && nums2[i] > nums2[t1.top()]) {
                t2[nums2[t1.top()]] = nums2[i];
                t1.pop();   
                //此处i--是为了不断弹出栈内所有比当前数小的数 
                //可能不直观 也可以改成while写法
                i--; 
            } 
            else {
                t1.push(i);
            }
        }

        vector<int> ans;
        for (int num : nums1) {
            ans.push_back(t2[num]);
        }

        return ans;
    }
};

root@NVR:~# dd if=/dev/sda1 of=/dev/mmcblk0 bs=1 skip=589303808 seek=589303808 c ount=134213632 ^C root@NVR:~# dd if=/dev/mmcblk0 bs=1 skip=589303808 count=1024 2>/dev/null | hexd ump -C 00000000 54 50 2d 4c 69 6e 6b 20 66 6f 72 6d 61 74 31 00 |TP-Link format1.| 00000010 00 00 00 01 00 00 02 00 00 00 00 01 00 00 00 48 |...............H| 00000020 00 00 00 00 00 00 00 00 00 00 00 04 31 00 00 00 |............1...| 00000030 00 00 00 03 00 00 00 00 00 00 00 04 32 00 00 00 |............2...| 00000040 00 00 00 04 00 00 00 00 00 00 00 04 35 00 00 00 |............5...| 00000050 00 00 00 01 00 00 00 01 00 00 00 0c 30 30 66 66 |............00ff| 00000060 30 30 34 31 62 35 30 00 00 00 00 00 00 00 00 00 |0041b50.........| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 f6 |................| 00000200 66 e0 58 f2 d8 7c 96 0b 1d 9f 31 d6 95 08 14 b7 |f.X..|....1.....| 00000210 10 00 02 02 00 40 20 20 43 9f 92 ec 77 7f 35 61 |.....@ C...w.5a| 00000220 4f f2 fb bc 7f 83 19 ce f7 8c d6 88 9f 33 8b da |O............3..| 00000230 da e8 c2 fd 08 0e 32 9a 20 67 85 fe 88 b9 b7 61 |......2. g.....a| 00000240 74 97 aa 32 0d a5 b4 c6 d7 7f d7 51 52 4f 79 aa |t..2.......QROy.| 00000250 aa 1b 17 55 36 45 b1 04 95 73 b9 52 2b d8 c0 d7 |...U6E...s.R+...| 00000260 dc d7 b0 12 08 2d 65 1e 19 b9 c7 37 78 cc 4d fb |.....-e....7x.M.| 00000270 f3 6e 10 b7 a5 5c 27 e3 0f fc 30 d5 74 cc 8d f1 |.n...\'...0.t...| 00000280 e3 42 25 2b 26 ec de 1f 7f af be 03 52 92 27 4d |.B%+&.......R.'M| 00000290 0d 33 6b 71 36 d7 d3 30 dc 24 8d d4 59 84 b5 ff |.3kq6..0.$..Y...| 000002a0 09 3e 41 a9 b4 54 e4 bf e9 50 04 f5 61 3b a4 8e |.>A..T...P..a;..| 000002b0 9b de 27 d6 bc e6 43 9e 91 dd 53 8a af 55 52 ac |..'...C...S..UR.| 000002c0 9b 51 c4 07 7e 05 1b 78 1e 43 e2 27 96 33 35 8f |.Q..~..x.C.'.35.| 000002d0 57 91 8f 4e 23 af 9a 36 05 a7 0b b5 a8 c4 c8 53 |W..N#..6.......S| 000002e0 53 01 ac 19 c3 37 b6 e6 91 11 2d e8 e4 66 d7 88 |S....7....-..f..| 000002f0 77 14 31 d1 2e 05 0f fd 32 65 be 6b 7c 24 84 a8 |w.1.....2e.k|$..| 00000300 65 11 27 c1 95 8c 0b eb 2e 90 7b cd 17 ce cd 7a |e.'.......{....z| 00000310 07 f4 32 24 95 aa 47 9e 7c 8f 84 fd 3b dc 0c 67 |..2$..G.|...;..g| 00000320 07 29 ef 42 3f 95 f1 03 b5 da 47 60 fc e8 14 e2 |.).B?.....G`....| 00000330 41 53 d9 48 50 57 2f 20 9a 82 a0 37 42 54 0d b1 |AS.HPW/ ...7BT..| 00000340 10 41 10 a9 37 74 a7 e2 01 91 97 63 87 fc f8 8b |.A..7t.....c....| 00000350 59 c3 10 5d 1f 29 70 77 ec 5a 5d b1 47 ab c0 d7 |Y..].)pw.Z].G...| 00000360 53 61 b5 47 cd 7d d6 bb d3 98 49 00 b0 30 c4 f9 |Sa.G.}....I..0..| 00000370 62 3d 14 95 1e 72 c5 d1 a6 41 27 5d 62 c7 ea a6 |b=...r...A']b...| 00000380 0d fc 5d aa 87 f2 2c 94 db 00 22 f7 95 82 34 ac |..]...,..."...4.| 00000390 e0 a4 4c 63 fa f5 a5 3e 46 14 1e 97 01 69 ad 66 |..Lc...>F....i.f| 000003a0 b6 b3 d1 df 5b 1a 98 8e bd d2 16 b4 f4 ac a7 33 |....[..........3| 000003b0 f1 23 05 9c bc 9e 59 30 fd a3 1a 07 13 d9 f0 f0 |.#....Y0........| 000003c0 fe 95 d1 01 d1 b1 b9 a5 80 6a 57 fa 28 f7 28 c7 |.........jW.(.(.| 000003d0 b3 55 a7 b0 c6 56 b1 6c b4 a7 6f 2f e3 be 29 54 |.U...V.l..o/..)T| 000003e0 4f 13 e1 98 8f 65 b7 d7 00 d1 29 e5 3c 00 0b 69 |O....e....).<..i| 000003f0 dc 12 9a 4e 37 23 1d e5 19 bc b8 1e 0e 27 d3 9c |...N7#.......'..| 00000400 这样可以读写,但是为什么打不开呢
10-14
你已经能成功用 `dd` 读写 `/dev/mmcblk0`,说明: ✅ **设备是存在的** ✅ **你可以访问它(至少部分偏移处可读)** ✅ **权限没问题,内核也识别了该设备** 但问题是: > ❌ `fdisk -l /dev/mmcblk0` 提示 `can't open '/dev/mmcblk0'` > ✅ 而 `dd if=/dev/mmcblk0 ...` 却可以正常工作 这看起来矛盾,但实际上有明确的解释。 --- ## 🔍 根本原因分析 ### 🚫 `fdisk` 失败 ≠ 设备不可访问 `fdisk` 是一个高级分区工具,它在打开设备时会做很多额外检查,比如: 1. **尝试获取设备大小(通过 `BLKGETSIZE` 或 `BLKGETSIZE64` ioctl)** 2. **验证是否为“合法块设备”** 3. **读取前几个扇区解析分区表** 4. **调用 `stat()` 检查设备类型** 而 `dd` 只是直接进行 `read()`/`write()` 系统调用,绕过了这些检查。 所以: 👉 **`dd` 能用说明设备基本可用** 👉 **`fdisk` 打不开,是因为某些元数据查询失败** --- ## ✅ 最可能的原因:**`ioctl(BLKGETSIZE)` 失败** 这是最常见的导致 `fdisk` 打不开设备的问题。 ### 验证方法: 运行这个命令看看能否获取设备容量: ```bash blockdev --getsize64 /dev/mmcblk0 ``` 或者: ```bash blockdev --getsize /dev/mmcblk0 ``` ❌ 如果输出: ``` blockdev: failed to get size for /dev/mmcblk0: Inappropriate ioctl for device ``` ✅ 那么这就是问题所在! > 💡 `fdisk` 内部依赖 `ioctl(BLKGETSIZE)` 获取总扇区数。如果这个调用失败,`fdisk` 就认为设备无效,直接拒绝打开,即使你能 `dd` 读写。 --- ## 🧾 为什么 `ioctl(BLKGETSIZE)` 会失败? 虽然你可以 `dd` 读写,但以下情况会导致 `BLKGETSIZE` 失败: | 原因 | 说明 | |------|------| | 🔹 eMMC 驱动未完全初始化 | 内核知道设备存在,但尚未完成容量探测 | | 🔹 设备处于某种异常状态 | 如刚从低功耗唤醒、通信不稳定 | | 🔹 分区表损坏或非法 | 某些旧版 `fdisk` 更严格 | | 🔹 使用了虚拟设备或 loop 设备模拟 | 不支持所有 ioctl | | 🔹 内核 mmc 驱动 bug | 特定 SoC 平台(如海思 HI35xx)常见 | --- ## ✅ 解决方案 & 替代办法 ### ✅ 方案一:忽略 `fdisk` 错误,继续使用 `dd` 和其他工具 既然 `dd` 可以读写,你就**完全可以操作这个设备**。 #### 推荐替代查看方式: ```bash # 查看设备大小(比 fdisk 更底层) blockdev --getsize64 /dev/mmcblk0 # 显示人类可读格式 numfmt --to=iec --suffix=B --format="%.2f" $(blockdev --getsize64 /dev/mmcblk0) ``` ```bash # 查看是否有分区信息(手动读 MBR) dd if=/dev/mmcblk0 bs=512 count=1 2>/dev/null | hexdump -C | head -20 ``` MBR 第 446 字节开始是分区表,你可以看到类似: ``` 000001be 80 00 01 00 0b fe ff ff 3f 00 00 00 7f ff ff 00 |........?.......| ``` 表示有一个主分区。 --- ### ✅ 方案二:尝试重新探测设备 有时设备刚插入或系统刚启动,驱动还没完全准备好。 ```bash # 通知内核重新扫描设备 echo 1 > /sys/block/mmcblk0/device/rescan 2>/dev/null || echo "rescan not supported" # 或者重新探测整个 MMC 主机 echo 1 > /sys/class/mmc_host/mmc0/scan 2>/dev/null ``` 然后再次尝试: ```bash blockdev --getsize64 /dev/mmcblk0 sudo fdisk -l /dev/mmcblk0 ``` --- ### ✅ 方案三:用 `lsblk` 替代 `fdisk` ```bash lsblk /dev/mmcblk0 ``` 输出示例: ``` mmcblk0 179:0 0 7.4G 0 disk ├─mmcblk0p1 179:1 0 128M 0 part /boot └─mmcblk0p2 179:2 0 7.3G 0 part / ``` 这个命令不依赖 `BLKGETSIZE`,通常更稳定。 --- ### ✅ 方案四:升级 `fdisk` 工具(来自 `util-linux`) 老版本 `fdisk`(如 BusyBox 自带的)对设备要求高。 检查你是哪个 `fdisk`: ```bash which fdisk fdisk --version ``` 如果是 `BusyBox fdisk`,功能有限,建议安装完整版: ```bash apt install util-linux # Debian/Ubuntu # 或 opkg install util-linux # OpenWrt 类系统 ``` 然后使用: ```bash /sbin/fdisk -l /dev/mmcblk0 ``` --- ## 🛠️ 进阶调试:手动测试 ioctl 是否成功 写一个 C 程序测试 `BLKGETSIZE64` 是否成功: ```c #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/fs.h> int main() { int fd = open("/dev/mmcblk0", O_RDONLY); if (fd == -1) { perror("open"); return 1; } unsigned long long size; if (ioctl(fd, BLKGETSIZE64, &size) == -1) { perror("ioctl BLKGETSIZE64 failed"); close(fd); return 1; } printf("Device size: %llu bytes (%.2f GiB)\n", size, size / (1024.0*1024.0*1024.0)); close(fd); return 0; } ``` 编译运行: ```bash gcc test_size.c -o test_size sudo ./test_size ``` 如果报错 `Inappropriate ioctl for device`,那就是内核驱动没实现这个 ioctl。 --- ## ✅ 总结 | 现象 | 原因 | 解决方案 | |------|------|-----------| | `dd` 能读写但 `fdisk` 打不开 | `BLKGETSIZE` ioctl 失败 | 改用 `blockdev`, `lsblk`, `hexdump` | | `blockdev --getsize64` 失败 | 驱动未返回设备容量 | 尝试 `rescan` 或重启 | | `fdisk` 报错而其他工具正常 | BusyBox 版本太简陋 | 安装完整 `util-linux` | --- ## ✅ 结论 > ✅ **你的 `/dev/mmcblk0` 是可用的!** > ⚠️ `fdisk` 打不开只是因为它太“挑食”,不是设备有问题。 > ✅ 继续用 `dd`, `blockdev`, `lsblk`, `hexdump` 等工具即可安全操作。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值