C语言强化(五)输出一串数中最小的 k 个

有时候题目看似很简单,似乎非常容易实现,但是,你考虑过效率了吗?

通过这道题,你可以掌握

  • 简单的插入排序
  • 算法最优化的技巧

题目:输入 n 个整数,输出其中最小的 k 个。

例如输入 1,2,3,4,5,6,7 和 8 这 8 个数字,则最小的 4 个数字为 1,2,3 和 4。

看到此题,第一反应就是对这串数字进行排序,然后遍历角标0~3的数字打印出来,很简单嘛~~

怎么可以这么简单,仔细一看,题目只是要求最小的N个数字啊,这样子对整个数组进行排序有必要吗?

只需要4个最小的,也就意味着只要一个数比现有的4个最小数大,那么我们就可以将它永远永远遗忘掉,而不是还把他插入到数组中,把他插入到数组中,等一下有新的值插进来,还要和他多比较一次,无形中增加了比较次数!

思路

写一个函数sorting(),能插入值并对数组进行排序,注意原数组已经排好顺序

新建vector,遍历所给数组,

对于之前的4个元素,只是执行sorting函数

对于之后的元素,执行sorting函数,将最上面值pop出去

源代码

#include <stdio.h>
#include<stdlib.h>
#include <iostream>
#include<sstream>
#include <vector>

using namespace std;

/**
查找最小的 k 个元素(数组)
题目:输入 n 个整数,输出其中最小的 k 个。
例如输入 1,2,3,4,5,6,7 和 8 这 8 个数字,
则最小的 4 个数字为 1,2,3 和 4。

思路
写一个函数sorting(),能插入值并对数组进行排序,注意原数组已经排好顺序
新建vector,遍历所给数组,
	对于之前的4个元素,只是执行sorting函数
	对于之后的元素,执行sorting函数,将最上面值pop出去
*/

/**
sorting
vt:所给数组
value:要插入的值
从顶到底遍历vector
如果value比遍历到的结点值小,则交换位置
否则,因为原数组已经排好顺序,后面的数都比当前的数小,所以停止,跳出循环
*/
void sorting(vector<int> &vt,int value){
	vt.push_back(value);
	for(int i = vt.size()-2;i>=0;i--){
		if(value<vt[i]){
			if(i<vt.size()-1)
				vt[i+1]=vt[i];
			vt[i]=value;
		}else{
			break;
		}
	}
}
/**
findLastN
寻找最小N个数
*/
void findLastN(vector<int> oriVt,vector<int> &finalVt,int n){
	//把第一个数直接放进去
	finalVt.push_back(oriVt[0]);
	//从第二个数开始遍历
	for(int i =1;i<oriVt.size();i++){
		//对于之前的4个元素,只是执行sorting函数
		sorting(finalVt,oriVt[i]);
		if(i>n-1){
			//对于之后的元素,执行sorting函数,将最上面值pop出去
			finalVt.pop_back();
		}
	}
}
void main()
{
	vector<int> finalVt;
	vector<int> oriVt;
	//创建原数组
	oriVt.push_back(2);
	oriVt.push_back(-1);
	oriVt.push_back(4);
	oriVt.push_back(0);
	oriVt.push_back(1);
	oriVt.push_back(12);
	oriVt.push_back(3);
	//显示原数组
	cout<<"原数组:"<<endl;
	for(int i = 0;i<oriVt.size();i++){
		cout<<oriVt[i]<<endl;
	}
	//找出最小n个
	int n = 4;
	findLastN(oriVt,finalVt,n);
	cout<<"最小N个数组:"<<endl;
	for(int i = 0;i<finalVt.size();i++){
		cout<<finalVt[i]<<endl;
	}
	system("pause");
}

运行图

算法的优化,可以理解为一个词:吝啬

多一步浪费,多一分钱都不给!可以比较10次计算出来的,绝对不比较11次!

时间: 2024-10-11 00:40:28

C语言强化(五)输出一串数中最小的 k 个的相关文章

C语言强化(九)翻转句子中单词的顺序

这是到很常见的题目,非常简单,但你用到数据结构了吗,或者说你用对了吗? 通过这道题,你可以掌握: 如何将用户的输入,输出到控制台 如何分割字符串 如何正确使用数据结构 题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变. 句子中单词以空格符隔开.标点符号和普通字母一样处理. 例如输入"I am a student.",则输出"student. a am I". 思路 一.获取字符串 首先要能够获取到用户输入的一串字符串,有两点需要注意: 1.如果使

返回一组数中最大的K个(JS实现)

第一次见到类似题目大约是在六年前吧.一道简单的ACM题,自己费半天劲用土方法得出结果,跟别人用堆排序求得结果的时间效率相差数倍,使得笔者第一次深切领略到算法的魅力.六年之后,再一次被人问到这道题,"堆排序"瞬间蹦入脑海. 不同的是,当时玩C,现在玩Java和JS,最熟的就是JS了,于是用JS把算法写了出来: function topKMaxOfArr(k, arr){ function swap(a, b){ var t = arr[a]; arr[a] = arr[b]; arr[b

C语言强化(二)设计可以求最小元素的栈

上一篇详解了二叉树转双向链表,此篇作为[C语言强化]系列第二篇,来聊聊有关栈的一道题, 通过这道题,你可以掌握 如何使用栈"先进后出"的特性 如何巧妙地借助辅助栈 如何在结构体中定义可共享的静态成员变量 题目 看似很简单的求最小值函数,思路有很多很多.笔者首先想到每次push入栈都进行一次排序,使这个栈的栈顶永远是最小元素,然后就发现这是一个很蠢很蠢的想法,第一这样做会改变了栈的结构,第二不满足题目对时间复杂度的要求. 愚蠢归愚蠢,还是有点用的.既然不能改变原来栈的结构,那为何不弄俩栈

输出一串字符串中单词个数

#include <stdio.h> #include <stdlib.h> /* 输入一行字符串(单词和若干空格), 输出该行单词个数. */ int main(){ char ch, str[100]; int count = 0; gets(str); for (int j = 0; str[j] != '\0';++ j) if ((str[j + 1] == '\0') && (str[j] != ' ')) //到达末尾且不为空格,单词数+1 count

求一串数中的最值(空间换时间)

求最值 2014年9月19日 16:44:28 这只是个例子,可看明白了? 1 foreach (CircleInfo p in point) 2 { 3 //找出出现次数最多的数 4 allnum++; 5 temp = p.Diameter; 6 count[temp]++; 7 if (count[temp] > maxNum) 8 { 9 maxNum = count[temp]; 10 most = temp; 11 } 12 }

找出一堆数中最小的前K个数

描写叙述: 给定一个整数数组.让你从该数组中找出最小的K个数 思路: 最简洁粗暴的方法就是将该数组进行排序,然后取最前面的K个数就可以. 可是,本题要求的仅仅是求出最小的k个数就可以,用排序能够但显然有点浪费.比方让求10000个整数数组中的最小的10个数.用排序的话平均时间复杂度差为Nlog(N). 于是想到了,用堆来实现,可是自己实现又太麻烦.想到了java里面的TreeSet,先将K个数放入TreeSet中.因为TreeSet会对里面的元素进行排序.所以在TreeSet中的元素是有序的.以

C语言强化(十一)二叉树镜像变化 | 要求:不使用递归

用了这么久的递归,现在不让用递归了,你行么? 通过这道题,你可以学会 如何镜像变化一棵二叉树 什么是递归的本质 如何巧妙地使用辅助栈 题目: 输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点. 要求: 不使用递归 例如输入: 输出: 将二叉树镜像变化的方法很简单,只要把所有节点的左右节点对调就行了,使用递归可以非常容易的实现. 如下为递归方法实现镜像变化的函数 /** 二叉树镜像变化--递归方法实现 */ void Revertsetree_R

C语言强化(八)判断序列是不是二叉查找树的后序遍历结果

前面聊了一系列关于链表相交的问题,本篇博文,让我们通过一道简单的判断题,复习复习数组和二叉树. 通过这道题,你可以掌握 二叉查找树的规律 后序遍历的特点 递归的使用 题目 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回 true,否则返回 false. 例如输入 5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: 因此返回 true. 如果输入 7.4.6.5,没有哪棵树的后序遍历的结果是这个序列,因此返回 false. 看到二元查找树(or二

【C语言】在全系1000个学生中,征集慈善捐款当总数达到10万的时候,停止捐款,统计人数,并输出平均捐款数

//在全系1000个学生中,征集慈善捐款当总数达到10万的时候,停止捐款,统计人数,并输出平均捐款数 #include <stdio.h> int main() { float sum=0; float amount; int count=0; int i; for(i=0;i<1000;i++) { printf("请输入捐款金额:"); scanf("%f",&amount); sum=sum+amount; count++; if(s