求数组中绝对值最小的元素

  给定一个有序数组a(从小到大排列),数组中的数据有正有负,找出这个数组中的绝对值最小的元素。最先到的自然是从头到尾依次遍历数组中的每个元素,找出绝对值最小的元素。这是最简单的方法,不过它并没有用到数组有序这个特性,现在我们来看看有没有更好的方法。题目要求在数组中查找元素,并且此数组有序,那么可以想到用二分法来处理。

  首先我们先看一下如果数组中元素全部为正数或者全部为负数的情况:

  • 如果a[0]>0,那么数组中所有元素均为正数,则a[0]为绝对值最小的元素
  • 如果a[len-1]<0,那么数组中所有元素均为负数,则a[len-1]为绝对值最小的元素

  当数组中元素有正有负时,绝对值最小的元素在正负数的交界点处,这是只需要比较交界点相邻两数绝对值的大小,返回绝对值小的即可。设a[mid]为数组的中间元素,那么可以以如下步骤进行查找:

  • 如果a[mid]<0,因为数组是升序,说明绝对值最小的数不会出现在a[mid]左边,需要在mid以右的区间进行查找
  • 如果a[mid]>0,因为数组是升序,说明绝对值最小的数不会出现在a[mid]右边,这里同时判断与a[mid]相邻且在其左侧的a[mid-1]元素的正负,如果为负数,那么说明这两个数是数组中正负交界点,返回这两个数的绝对值较小的,如果a[mid-1]不为负,那么需要在mid以左的区间进行查找
  • 如果a[mid] == 0,那么a[mid]即为绝对在最小的元素
  • 区间范围改变,对区间中的mid重新赋值,重复上述步骤

  根据上面的步骤写出代码:

 1 int FindMinAbs(int a[], int len)
 2 {
 3     //如果a数组第一个元素>0,则a[0]之后的数均>0,且都比a[0]大
 4     if(a[0]>0)
 5         return a[0];
 6     //如果a数组最后一个元素<0,则a[len-1]之前的数均<0,且都比a[len-1]小,所以abs(a[len-1])最小
 7     else if(a[len-1]<0)
 8         return a[len-1];
 9
10     int left=0, right=len-1, mid=(left+right)/2;
11     int i=0;
12
13     //如果a[0]<0,a[len-1]>0,那么绝对值最小的数一定出现在正负交界点
14     while(true)
15     {
16         cout<<"mid="<<mid<<", a[mid]="<<a[mid]<<", left="<<left<<", right="<<right<<endl;
17         if(a[mid]<0)
18         {
19             left = mid+1;
20         }
21         else if(a[mid]>0)
22         {
23             //如果a[mid]和a[mid-1]一正一负,所以只需判断他俩的abs大小
24             if(a[mid]*a[mid-1] <= 0)
25                 return -a[mid-1] < a[mid]? a[mid-1]:a[mid];
26             right = mid-1;
27         }
28         else
29             return a[mid];
30
31         mid = (left+right)/2;
32     }
33 }
时间: 2024-10-29 10:46:47

求数组中绝对值最小的元素的相关文章

[经典面试题]排序数组中绝对值最小元素

[题目] 题目为: 有一个已经排序的数组(升序),数组中可能有正数.负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现 例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4. [分析] 给定数组是已经排好序的,且是升序,没有重复元素. 一个简单的思路,就是一次性遍历数组,求出数组的元素的绝对值的最小值,这样的时间复杂度为O(n). 但是,这样就浪费了题目的一个条件:数组是已经排好序的.所以,需要对原来的题目

找出有序数组中绝对值最小的数

问题: 一个有序数组,值有可能有负值,也有可能没有,现需要找出其中绝对值最小的值. 方法1: 遍历数组,找到绝对值最小值,时间复杂度O(n),n为元素个数. 方法2: 二分查找,因为数组有序,可以利用二分查找,时间复杂度O(logn). 分析步骤: 如果第一个数为正数,说明整个数组没有负数,直接返回第一个数 如果最后一个数为负数,说明整个数组没有正数,直接返回最后一个数 数组元素有正有负,说明绝对值最小的元素肯定在正负数交界处,需要二分查找上场: 如果a[mid]<0,因为数组是升序,说明绝对值

c++求数组中的最小(大)的n位数

#include <iostream> using namespace std; class MaxHash { public: MaxHash(int n) { data = new int[n]; size = n; } void Insert(int a[], int n) { int i = 0; for (; i < size; i++)//初始化数组 { data[i] = a[i]; } int j = size / 2; while (j >= 0)//构造堆 {

微软算法100题69 求旋转数组中的最小元素

69.求旋转数组中的最小元素.题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1 思路: 1. 可以从左到右扫描整个数组,找出最小的那个,时间复杂度是o(n) 2. 也可以利用旋转数组本身的特性,即部分有序,然后借助二分查找的方法来解决,先找中间点mid = left + (right - left)/2, 如果a[le

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

用C随机产生的正整数存到数组中,并求数组中的所有元素最大值、最小值、平均值以及各元素之和,及第二大值。

用 C 求一组随机数的第二大值,不能通过对整体排序求得 1 随机产生20个[10 , 50]的正整数存到数组中,并求数组中的所有元素最大值.最小值.平均值以及各元素之和,及第二大值.        int a[20];    int sum = 0; //存储数组元素的和    //为数组赋值    printf("数组中的元素为:\n ");    for (int i = 0; i < 20; i ++) {        a[i] = arc4random() % 41 +

【c语言】输入一个递增排序的数组的一个旋转,输出旋转数组中的最小元素

//旋转数组的最小数字 //题目:把一个数组最開始的若干个元素搬到数组的末尾.我们称之为数组的旋转. //输入一个递增排序的数组的一个旋转.输出旋转数组中的最小元素. //比如:数组{3.4,5,1,2}为{1,2.3.4.5}的一个旋转,最小元素是1. #include <stdio.h> #include <assert.h> int min_equ(int *src, int left, int right) { int i = 0; int ret = src[left];

【编程题目】旋转数组中的最小元素☆

69.旋转数组中的最小元素(数组.算法).题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为 1. 我就用了最简单的方法.而且开始还没考虑1, 0, 1 ,1这样的情况 /* 69.旋转数组中的最小元素(数组.算法). 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个 排好序的数组的一个旋转

输入一个整形数组(可能有正数和负数),求数组中连续子数组(最少有一个元素)的最大和。要求时间复杂度为O(n)(解决)

输入一个整形数组(可能有正数和负数),求数组中连续子数组(最少有一个元素)的最大和.要求时间复杂度为O(n). 输入描述: [重要]第一行为数组的长度N(N>=1) 接下来N行,每行一个数,代表数组的N个元素 输出描述: 最大和的结果 输入例子1: 8 1 -2 3 10 -4 7 2 -5 输出例子1: 18 思路:对输入的数组进行计算, import java.util.Scanner; public class Main { public static void main(String[]