C语言数组中如何挑选第n大的值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言数组中如何挑选第n大的值相关的知识,希望对你有一定的参考价值。

整数型数组已经 数组元素个数m已知 输出第n大元素的位置 其中m>n 怎么做??最好能给个C语言的例子,谢谢~~
我想问的是第n大元素的位置
比如a=1,2,3,4,5,6,7
7个元素中第3大的位置,输出4
不是问第3大的值。

在函数中利用动态数组复制原数组,并生成一个下标数组与复制数组相对应

对复制后的数组进行冒泡排序n次,冒泡的同时对下标数组进行相应的操作,保证这两个数组的对应关系

第n次冒泡就可以从下标数组得到所需的位置信息了。

也可以参考下面这段代码,写了这么多,请采纳吧。

int findN(int arr[], int m, int n)
int *index = (int *)malloc(n*sizeof(int));
bool flag=0;
int i,j;

for (i=0; i<n; i++)

index[i] = 0;
for (j=0; j<m; j++)

if (arr[index[i]]<=arr[j])

for (int k=0; k<i+1; k++)

if (j==index[k])

flag = 1;
break;


if (!flag)

index[i] = j;

else

flag = 0;
continue;




int tmp = index[n-1];
free(index);
return tmp;


int main()

int a[5] = -1, 3, 2 ,0,-3;
int n=1;
printf("数组为:\\n");
for (int i=0; i<5; i++)

printf("%d  ", a[i]);

printf("\\n");

printf("请输入n:\\n");
scanf("%d", &n);
printf("\\n");

printf("第%d大的元素下标为: %d ",n,findN(a,5,n));
printf("\\n");

参考技术A int iArry1[m] =  0 ;
//do sth to stuff iArry1 here;

//将iArry1排序,
int nMax = iArry1[0];nMin= iArry1[0];
int nMaxIndex = 0; 
for(int i = 0; i < m; i++)

    if(iArry1[i] > nMax)
     
        nMax = iArry1[i];
        nMaxIndex = i; 
     
    if(iArry[i] < nMin)
    
        nMin = = iArry1[i];
    


iArry1[nMaxIndex] = nMin - 1;   
for(int i = 1; i < n; i++)
 
    nMax = iArry1[0];
    nMaxIndex = 0;  
    for(int j = 0; j < m; j++)
        
            if(iArry1[j] > nMax)
             
                nMax = iArry1[j]; 
                nMaxIndex = j;  
              
           
    iArry1[nMaxIndex] = nMin - 1;     

printf("第%d大的数字为:%d",n,nMax);

 以上代码没有考虑数字相同情况,并且没有对m,n等做检查,随手写的,就是说了下想法,具体是否有错误还需自行调试。

参考技术B 先排序
遍历数组 如果 a[i] != [i-1] n--
当 n ==1 时 此时数组下标即为所求值
参考技术C //#include "stdafx.h"//vc++6.0加上这一行.
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int m_n_s(int *p,int m,int n)
int a[100],i,j,k,x;
memcpy(a,p,m*(x=sizeof(int)));
for(k=(1<<x*8)-1;n;n--)
for(x=a[0],i=1;i<m;i++)
if(a[i]>x) x=a[j=i];
a[j]=k;

return j;

void main(void)
int a[100],n,i,j,k;
printf("Enter some data...\n");
for(i=0;i<100;i++)
if(scanf("%d",a+i)!=1)
break;
printf("Type n(n<%d)...\nn=",i);
fflush(stdin);
scanf("%d",&n);
printf("第%d大的下标是%d\n",n,m_n_s(a,i,n));
参考技术D 从小到大排序,输出第n个元素

找出数组中每个数右边第一个比它大的元素--时间复杂度o(n)单调栈解法

题目:给定一个整型数组,数组元素随机无序的,要求打印出所有元素右边第一个大于该元素的值。

如数组A=[1,5,3,6,4,8,9,10] 输出[5, 6, 6, 8, 8, 9, 10, -1]

如数组A=[8, 2, 5, 4, 3, 9, 7, 2, 5] 输出[9, 5, 9, 9, 9, -1, -1, 5, -1]

1、暴力遍历

我们很容易想到复杂度为O(n^2)的解法,遍历数组中的每一个后面所有元素,找到第一个大于它的,输出即可。代码实现如下:

public int[] findMaxRight(int[] array)  
        if(array == null) 
            return array;
        
        int size = array.length;
        int[] result = new int[size];
        for(int i = 0; i < size-1; i++) 
            for(int j = i+1; j < size; j++) 
                if(array[j] > array[i]) 
                    result[i] = array[j];
                    break;
                
            
        
        result[size-1] = -1;//最后一个元素右边没有元素,所以肯定为-1
        return result;
    

2、借助栈,时间复杂度O(n)

如果要求时间复杂度为O(n)呢,能不能遍历一次数组中元素,就可以找到右边第一个大于它的元素呢,当然是可行的,不过要借助数据结构栈。

具体思路是:我们用栈来保存未找到右边第一个比它大的元素的索引(保存索引是因为后面需要靠索引来给新数组赋值),初始时,栈里放的是第一个元素的索引0值。

步骤如下:

(1)初始化栈,里面为第一个元素索引0值;

(2)遍历到下一个元素A[i]

1) 如果栈不为空且当前遍历的元素值A[i]大于栈顶的元素值A[stack.peek()],说明当前元素正好是栈顶元素右边第一个比它大的元素,将栈顶元素弹出,result[stack.pop()]=A[i]

继续遍历的元素值A[i]是否大于新栈顶元素值A[stack.peek()],如果大于,说明A[i]也是比A[stack.peek()]右边第一个比它大的元素,将栈顶元素弹出,result[stack.pop()]=A[i],一直循环,直到不满足条件1),即栈顶为空或是当前遍历的元素值小于栈顶元素索引处的值。

2) 如果栈为空,说明前面的元素都找到了比它右边大的元素,则直接将当前元素的索引放入栈中;

3)如果当前遍历的元素值A[i]小于栈顶元素索引的值A[stack.peek()],说明还未找到栈顶元素中右边第一个比它大的元素,直接将当前遍历的元素的索引入栈即可stack.push(i);

将i++,重复步骤(2)

(3)直到遍历完所有元素,如果栈不为空,说明栈中保存的全是未找到右边第一个比它大的数组索引,我们依次将这些栈元素出栈,并赋值result[stack.pop()]=-1即可。

以A=[8, 2, 5, 4, 3, 9, 7, 2, 5] 举例

1) 初始栈顶元素数组的第一个索引0,栈顶A[stack.peek()]=A[0]=8

2) 遍历到下一个元素值为2,它比栈顶A[stack.peek()]=A[0]=8元素值小,即上面第(2)步中的第3)种情况,直接将该元素的索引入栈,栈中元素是1, 0, 栈顶A[stack.peek()]=A[1]=2

3) 遍历到下一个元素值为5,它比栈顶A[stack.peek()]=A[1]=2元素值大,即上面第(2)步中的第1)种情况,将栈顶元素出栈,并且赋值result[stack.pop()]=result[1]=5,现在栈中还剩下 0, 栈顶A[stack.peek()]=A[0]=8

接着判断当前遍历的元素值5是否在大于栈顶A[stack.peek()]=A[0]=8,发现小于栈顶元素,即上面第(2)步中的第3)种情况,直接将该元素的索引入栈,栈中元素是2, 0, 栈顶A[stack.peek()]=A[2]=5

4) 遍历到下一个元素值为4,它比栈顶A[stack.peek()]=A[2]=5元素值小,直接将该元素的索引入栈,栈中元素是3,2, 0, 栈顶A[stack.peek()]=A[3]=4

5) 遍历到下一个元素值为3,它比栈顶A[stack.peek()]=A[3]=4元素值小,直接将该元素的索引入栈,栈中元素是4,3,2, 0, 栈顶A[stack.peek()]=A[4]=3

6) 遍历到下一个元素值为9,它比栈顶A[stack.peek()]=A[4]=3元素值大,将栈顶元素出栈,并且赋值result[stack.pop()]=result[4]=9,现在栈中还剩下3, 2, 0, ....重复这个步骤,最终都因为9比栈顶元素大,栈中元素出栈,最终result[3]=9, result[2]=9, result[0]=9, 直到栈中元素都出栈了,栈为空,变成上面的(2) 3) 情况,直接将当前元素索引值存入栈。即栈顶A[stack.peek()]=A[5]=9

7) 遍历到下一个元素值为7,它比栈顶A[stack.peek()]=A[5]=9元素值小,直接将该元素的索引入栈,栈中元素是6,5, 栈顶A[stack.peek()]=A[6]=7

8) 遍历到下一个元素值为2,它比栈顶A[stack.peek()]=A[6]=7元素值小,直接将该元素的索引入栈,栈中元素是7, 6,5, 栈顶A[stack.peek()]=A[7]=2

9) 遍历到下一个元素值为5,它比栈顶A[stack.peek()]=A[7]=2元素值大,将栈顶元素出栈,并且赋值result[stack.pop()]=result[7]=5,现在栈中还剩下6, 5, 栈顶元素A[stack.peek()]=A[6]=7比当前处理的元素值5大,所以将当前元素的索引值入栈,栈中变成8, 6, 5

由于元素遍历完了,栈中还保存的元素代表该索引处找不到右边第一个比它大的元素值了,所以挨个将栈中元素出栈,并赋值result[8]=-1, result[6]=-1, result[5]=-1

输出[9, 5, 9, 9, 9, -1, -1, 5, -1]

可以看到只需要遍历一次,就把数组中每个右边比它大的元素输出了。

具体代码实现如下:

public int[] findMaxRightWithStack(int[] array) 
        if(array == null) 
            return array;
        
        int size = array.length;
        int[] result = new int[size];
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        int index = 1;
        while(index < size) 
            if(!stack.isEmpty() && array[index] > array[stack.peek()]) 
                result[stack.pop()] = array[index];
             else 
                stack.push(index);
                index++;
            
        
        if(!stack.isEmpty()) 
            result[stack.pop()] = -1;
        
        return result;
    

总结:

第二种方是以空间换时间,用到了数据结构栈,用到了单调栈思想,单调栈可以用来解决一类问题,单调栈是指:栈内元素保持一定单调性(单调递增或单调递减)的栈。这里的单调递增或递减是指的从栈顶到栈底单调递增或递减。既然是栈,就满足后进先出的特点。与之相对应的是单调队列。

具体可参考这篇文章:单调栈原理及应用 详解 附各种类型的题目练习

利用单调栈解决此问题,尤其在数据量特别大的时候,第二种方法带来的时间上的优势会非常明显。

以上是关于C语言数组中如何挑选第n大的值的主要内容,如果未能解决你的问题,请参考以下文章

c语言求数组第k大的数字

用C语言把一个数组中的值按逆序重新存放?

c语言如何判断一个数组中重复元素的个数,并输出这个个数的值?

急!!!C语言:输出两组数组中相同的数字

C语言 如何将一个二维数组的值全部替换成另一个二维数组

c语言中,。编写程序求斐波那契数列的第n项和前n项之和。大家看好是【第】n项的值和前n项的合= =。