BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #99811同步于 2020/3/22
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

【问题】C++ For 循环遍历 Vector 出错

f2013210257
2020/3/22镜像同步20 回复
前阵子朋友在做[Leetcode 面试题40. 最小的k个数](https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/)时,遇到这个问题: ## 错误示例 使用 For 循环遍历 Vector,终止条件涉及到 Vector 的大小,如果直接用 `arr.size()-k` 来表示终止条件,程序执行会报 Segmentation fault: ```C++ int end = arr.size() - k; int start = arr.size() - 2; for (int i=start; i >= arr.size()-k; i--) { // i >= arr.size()-k; 提示段错误 ``` 执行输出: ```Shell ... live-18327 0 live-18328 0 live-18329 0 live-18330 0 live-18331 0 live-18332 0 live-18333 0 Segmentation fault (core dumped) ``` ## 正确示例 如果事前用一个变量 end 表示终止条件,然后在 for 里面使用 end,就没有问题。 ```C++ int end = arr.size() - k; int start = arr.size() - 2; for (int i=start; i >= end; i--) { // i >= end; 则正确执行 ``` 执行输出: ```Shell $ ./a.out live8 0 live7 0 live6 0 live5 0 live4 0 live3 0 live2 0 live1 0 live0 0 1 2 3 3 3 3 3 3 3 3 ``` 但是通过验证(程序里面打印出对应的值),这个值是**`arr.size() - k`始终没变的**,而且为0的,不清楚为什么 i 就递减到负数去了。 ## 附录 完整的代码: ```C++ #include <iostream> #include <vector> using namespace std; class Solution { public: void minHeap(vector<int>&arr, int heapSize, int index) { int left = index*2+1 ; int right = index*2+2; int smallest = index; if (right < heapSize && arr[right] < arr[index]) { smallest = right; } if (left < heapSize && arr[left] < arr[smallest]) { smallest = left; } if (smallest != index) { swap(arr[index], arr[smallest]); minHeap(arr, heapSize, smallest); } } void buildHeap(vector<int> &arr) { for (int i = arr.size() / 2 - 1; i >=0; i--) { minHeap(arr, arr.size()-1, i); } } vector<int> getLeastNumbers(vector<int>& arr, int k) { vector<int> ret; if (k == 0) return ret; buildHeap(arr); ret.push_back(arr[0]); swap(arr[0], arr[arr.size()-1]); int end = arr.size() - k; int start = arr.size() - 2; for (int i=start; i >= arr.size()-k; i--) { // i >= arr.size()-k; 提示段错误 i >= end; 则正确 minHeap(arr, i, 0); cout << "live" << i << " " << arr.size() - k << endl; ret.push_back(arr[0]); swap(arr[0], arr[i]); } return ret; } }; void print(std::vector<int> const &input) { for (int i = 0; i < input.size(); i++) { std::cout << input.at(i) << ' '; } } int main() { Solution testIns; vector<int> test = {2,1,3,3,3,3,3,3,3,3}; vector<int> result = testIns.getLeastNumbers(test, 10); print(result); return 0; } ``` 更多相关结果: https://gist.github.com/Duan-JM/3ce78a6f95a4d03cbb2c34f1509ddda7
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
Crazysun机器人#1 · 2020/3/22
size函数返回的是无符号整数,应该跟这个有关
a912655391机器人#2 · 2020/3/22
size返回无符号整数,i是有符号数,无符号数与有符号数比较的时候,有符号数被视为无符号数。所以当i减到-1时,-1的补码是0xfff。。。就是最大的无符号数,所以这一轮的判断成功,进入循环,访问arr[-1] 引起段错误。而用end来作为条件则是有符号数与有符号数比较。
f2013210257机器人#3 · 2020/3/22
【 在 a912655391 的大作中提到: 】 : size返回无符号整数,i是有符号数,无符号数与有符号数比较的时候,有符号数被视为无符号数。所以当i减到-1时,-1的补码是0xfff。。。就是最大的无符号数,所以这一轮的判断成功,进入循环,访问arr[-1] 引起段错误。而用end来作为条件则是有符号数与有符号数比较。 确实是这样,谢了。以前上课的内容都还给老师了
yo1995机器人#4 · 2020/3/22
心疼c++
nuanyangyang机器人#5 · 2020/3/22
另外,C++有priority_queue这个东西。 而且,找最小的k个数,难道不应该用大顶堆吗?保持堆中的元素个数不超过k个,一旦超过,达到k+1个,就把最大的那个扔掉,剩下的就是k个最小的。
Lss1995机器人#6 · 2020/3/22
arr. size() - k是size_t类型,无符号整数范围 【 在 f2013210257 (Flyq@意涵团) 的大作中提到: 】 : [md] : 前阵子朋友在做[Leetcode 面试题40. 最小的k个数](https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/)时,遇到这个问题: : ...................
Lss1995机器人#7 · 2020/3/22
这题可以使用O(n) partition算法
nuanyangyang机器人#8 · 2020/3/22
Rust用户顺便来炫耀一下Rust实在是太好用了。 use std::collections::BinaryHeap; pub fn min_k<T: Copy + Ord>(nums: &[T], k: usize) -> Vec<T> { let mut heap = BinaryHeap::<T>::new(); for num in nums { heap.push(*num); if heap.len() > k { heap.pop(); } } heap.iter().cloned().collect::<Vec<_>>() } fn main() { let v = vec![3, 1, 4, 5, 9, 2, 6, 8, 7]; let mink = min_k(&v, 4); for num in mink { println!("{}", num); } }
BUPTLOLNOx机器人#9 · 2020/3/22
哇!!!flyq!!!你是我偶像