To prove safety offer face questions 29: More than half of the number of times the number that appears array

Title: The number of times a digital array appears generally exceeds the length of the array, find this number, for example, a length of the input array 9 (1,2,3,2,2,2,5,4,2,) . Since the number 2 appears five times, more than half the length of the array in the array, the output 2.

The idea at first glance by the individual is a sort function, and then determines the middle number of occurrences, as long as there is more than n / 2, the output directly.

In general, most intuitive algorithm interviewer will not be satisfied, then there is no better algorithm it?

This algorithm is inspired by fast sorting algorithm. In the random quick sort algorithm, we now array randomly select a number, and then adjust the order in an array of numbers such that the ratio of digital numbers smaller selected are ranked in its left, larger than the selected digital numbers are ranked in it right. If the selected index number is exactly n / 2, then this number is the median of the array. If its index greater than n / 2, then the median should be located to its left, then we can find it in the array on the left section. If its index of less than n / 2, then the median should be located to its right, then we can find it in the array to the right section. This is a typical recursive procedure, codes are as follows:

 1 int MoreThanHalfNum_Solution(vector<int> numbers) 
 2 {
 3     int length = numbers.size();
 4     if (numbers.empty() || length<0)
 5         return 0;
 6 
 7     int begin = 0;
 8     int end = length - 1;
 9     int middle = length >> 1;
10     int index = 0; 
11     //利用
12     while(the begin < End)
 13 is      {
 14          index = the Partition (Numbers, the begin, End);
 15          IF (index == Middle)
 16          {
 . 17              BREAK ;
 18 is          }
 . 19          the else  IF (index> Middle)
 20 is          {
 21 is              End index = - . 1 ; // the value of the left side portion in the array. 
22 is          }
 23 is          the else 
24          {
 25              the begin = index + . 1 ; // the value of the right part of the array.
26          }
 27      }
 28      // check whether the value exceeds half the length of the array 
29      int CNT = 0 ;
 30      for ( int I = 0 ; I <length; ++ I)
 31 is      {
 32          IF (Numbers [index] == Numbers [I])
 33 is              CNT ++ ;
 34 is      }
 35      IF (CNT * 2 > length) return Numbers [index];
 36  
37 [      return  0 ;
 38 is }

 

I. Based partition function O (n) algorithm

A algorithm

partition function ideas:

  • Using the first array element as a pivot point, namely Pivot;
  • A pointer used to scan the entire array, all smaller than all pivot left end into an array;
  • Finally, the pivot position into the middle of the array, the left pivot are all less than its number, contrary to the right, and returns the location information of the pivot;

 

 

 

 code show as below:

. 1  void the swap ( int & X, int & Y)
 2  {
 . 3      int T = X;
 . 4      X = Y;
 . 5      Y = T;
 . 6  
. 7  }
 . 8  int Partition (Vector < int > & the nums, int the begin, int End)
 . 9  {
 10      int pivot the nums = [begin]; // pivot (may be a random number between begin and end)
 . 11      // Last position the puts WHERE the no_larger Element.
 12 is      //凡是小于pivot的全部放到数组左端,pos指向<枢轴值的最后一个
13     //pos++指向不满足条件的(用于交换,将满足条件的换过来)
14     int pos = begin;
15     for (int i = begin + 1; i < end; ++i)
16     {
17         if (nums[i] < pivot)
18         {
19             pos++;
20             if (i != pos) //避免自身交换
21                 swap(nums[pos], nums[i]);
22         }
23 
24     }
25     swap(nums[pos], nums[begin]);
26     return pos;
27 }

算法分析
这种实现思路比较直观,但是其实并不高效。从直观上来分析一下,每个小于pivot的值基本上(除非到现在为止还没有遇见大于pivot的值)都需要一次交换,大于pivot的值(有可能需要被交换多次才能到达最终的位置。

算法二

算法思路

  • 就如快速排序中最常使用的那样,使用两个指针分别从头部和尾部进行扫描,头部遇到大于pivot的数和尾部遇到小于pivot的数进行交换;
  • 使用了两个指针,效率更高一点;避免使用swap函数

如果我们考虑用 Two Pointers 的思想,保持头尾两个指针向中间扫描,每次在头部找到大于pivot的值,同时在尾部找到小于pivot的值,然后将它们做一个交换,就可以一次把这两个数字放到最终的位置。一种比较明智的写法如下:

//Two Pointers思想的分割函数(begin为0,end为n-1)
int Partition(vector<int> &nums, int begin, int end)
{
    int pivot = nums[begin];//第一个记录作为枢轴(也可是在begin和end之间的随机数)
    while (begin < end)
    {
        while (begin < end && nums[end] >= pivot)
        {
            end--;
        }
        nums[begin] = nums[end];//尾部找到小于pivot的值,移到低端

        while (begin < end && nums[begin] <= pivot)
        {
            begin++;
        }
        nums[end] = nums[begin];//头部找到大于pivot的值,移到高端
    }

    nums[begin] = pivot;//枢轴基准归位

    return begin;
}

算法分析:赋值操作不多,效率会更高


 

二分Partition算法

快速排序算法

void quickSort(vector<int> &nums, int begin, int end)
{

    if (begin >= end) return;

    int index = partition(nums, begin, end);
    if (index>begin)
        quickSort(nums, begin, index-1);
    if (index<end)
        quickSort(nums, index+1, end);
}
调用:
quickSort(vec, 0, vec.size()-1); //end为n-1

 

 

Guess you like

Origin www.cnblogs.com/knis/p/12334095.html