返回信息流前阵子朋友在做[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
这是一条镜像帖。来源:北邮人论坛 / cpp / #99811同步于 2020/3/22
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
【问题】C++ For 循环遍历 Vector 出错
f2013210257
2020/3/22镜像同步20 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
size返回无符号整数,i是有符号数,无符号数与有符号数比较的时候,有符号数被视为无符号数。所以当i减到-1时,-1的补码是0xfff。。。就是最大的无符号数,所以这一轮的判断成功,进入循环,访问arr[-1] 引起段错误。而用end来作为条件则是有符号数与有符号数比较。
【 在 a912655391 的大作中提到: 】
: size返回无符号整数,i是有符号数,无符号数与有符号数比较的时候,有符号数被视为无符号数。所以当i减到-1时,-1的补码是0xfff。。。就是最大的无符号数,所以这一轮的判断成功,进入循环,访问arr[-1] 引起段错误。而用end来作为条件则是有符号数与有符号数比较。
确实是这样,谢了。以前上课的内容都还给老师了
另外,C++有priority_queue这个东西。
而且,找最小的k个数,难道不应该用大顶堆吗?保持堆中的元素个数不超过k个,一旦超过,达到k+1个,就把最大的那个扔掉,剩下的就是k个最小的。
arr. size() - k是size_t类型,无符号整数范围
【 在 f2013210257 (Flyq@意涵团) 的大作中提到: 】
: [md]
: 前阵子朋友在做[Leetcode 面试题40. 最小的k个数](https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/)时,遇到这个问题:
: ...................
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);
}
}