棋子

导航

两道考研算法设计题- 2010 2013

2010:

设将n(n>1)个整数存放到一维数组R中。试设计一个在时间和空间两方面都尽可能高效的算法,将R中保存的序列循环左移P(0<P<n)个位置,即将R中的数据由(x0,x1,…,xn-1)变换为(xp,xp+1,…,xn-1,x0,x1,…,xp-1)。要求:
  (1)给出算法的基本设计思想。
  (2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。
  (3)说明设计算法的时间复杂度和空间复杂度。

【解析】:

(1)前P个数依次进队,while(i<n-p) A[i]=A[i+p];P个数依次出队,进入数组末尾;

或者,使用数学里的分析方法:

循环左移p个位置,也就是将数组分为2部分,前一部分从0到p-1,后一部分从p到n-1,将数组的前一部分跟后一部分进行了交换。 

首先逆序前一部分,然后逆序后一部分,左后整个逆序。以此实现循环左移:酷酷的!

其数学原理:(a-1b-1)-1=ba

代码如下:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 
 5 void reverse(int a[],int begin,int end)
 6 {
 7     int i = begin, j = end,temp;
 8     while (i < j)
 9     {
10         a[i] = a[j];
11         a[j] = temp;
12         ++i;
13         --j;
14     }
15 }
16 void loop(int *a, int len, int p)
17 {
18     reverse(a, 0, p - 1);
19     reverse(a, p, len-1);
20     reverse(a, 0, len-1);
21 }
22 
23 int main()
24 {
25     int a[5] = { 12345 };
26     loop(a, 53);
27     for (int i = 0; i < 5; i++)
28     cout << a[i] << " ";
29     return 0;//输出结果:4 5 1 2 3
30 }
View Code

(3)时间复杂度O(N),空间复杂度O(1)。 

 

 

 

2013:

【解析:】

(1)算法思想:

首先保存整数序列的第一个数到res中,并计数count=1,然后从后往前(从前往后也一样)遍历,若是第二个数等于res,则count自增,否则count自减,若是count等于0,则res保存整数序列中将要遍历的下一个整数。

其次,我们来进行验证,遍历一遍整数序列,若是整数等于上一步中的res,则count自增,否则不做处理;如果最后count大于n/2,则说明res就是主元素,否则返回-1,说明主元素不存在。

(2)c++实现的代码如下:

 1 #include<iostream>
 2 using namespace std;
 3 int getNum(int *arr, int len)
 4 {
 5     int res=arr[0],count=1;
 6     while (len > 0)
 7     {
 8         if (arr[len] == res)
 9             count++;
10         else
11         {
12             --count;
13             if (count == 0)
14                 res = arr[len - 1];
15         }
16         len--;
17     }
18     return res;
19 }
20 int verify(int *arr, int len)
21 {
22     int count = 0;
23     int num = getNum(arr, len);
24     for (int i = 0; i < len;i++)
25     if (num == arr[i])
26         ++count;
27     if (count>len / 2)
28         return num;
29     else
30         return -1;
31 }
32 int main()
33 {
34     int arr[] = { 0,5,5,3,5,7,5,5 };
35     int result = verify(arr, 8);
36     cout << result << endl;
37     return 0;
38 }
View Code

update-2015-8-20:网上一段更简洁的代码:

 1 class Solution {
 2 public:
 3     int majorityElement(vector<int> &num) {
 4         int nTimes = 0;
 5         int candidate = 0;
 6         for(int i = 0; i < num.size(); i ++)
 7         {
 8             if(nTimes == 0)
 9             {
10                 candidate = num[i];
11                 nTimes = 1;
12             }
13             else
14             {
15                 if(candidate == num[i])
16                     nTimes ++;
17                 else
18                     nTimes --;
19             }
20         }
21         return candidate;
22     }
23 };

 

(3)数组遍历了两次,但是每次都是O(n),空间上只使用了几个辅助变量,所以时间复杂度为O(n),空间复杂度为O(1)。

 

posted on 2015-08-15 15:38  鼬与轮回  阅读(794)  评论(1编辑  收藏  举报