寻找多数元素
/*** -*- coding : utf-8 -*-* @Author : huangshengjiang* @Email : 1005542693@qq.com* @Date : 2016-09-21 11:15* @Last Modified Date : 2016-10-19 10:46* @FileName : 尋找多數(shù)元素.cpp*//*尋找多數(shù)元素.cpp基本概念 : 在數(shù)組A[1...n]中,如果有個數(shù)值的數(shù)量超過[n/2]個,則認為該數(shù)值為多數(shù)元素,返回該值.否則返回-1觀察結論 : 在數(shù)組中刪除任意兩個不同的數(shù)值,則原數(shù)組中的多數(shù)元素在新數(shù)組中仍然是多數(shù)元素.解決辦法1 : 數(shù)組表示,申明一個大小為max(A中最大的數(shù)值)的動態(tài)數(shù)組B[max](需要遍歷A),初始化為0.再對數(shù)組A遍歷,在B[A[i]]++;遍歷結束后,B[j]的值就是對應j=A[i]的數(shù)量.只要B[j]的值大于n/2下限,則輸出j,否則輸出-1評估1 : 時間復雜度為n*n*max,空間復雜度為max大小的數(shù)組.有一個嚴重的缺陷,申請了大量無用的空間max-n.如果max過大n偏小,極大浪費內存,也消耗cpu的功能.解決辦法2 : 鏈表表示,節(jié)點結構Node包含三個成員變量,value表示數(shù)值,count表示該數(shù)值的數(shù)量,next是指針,指向下一個Node.遍歷數(shù)組A,將A[i]與鏈表從頭到尾進行比較,若找到相應的value值,則count++;如果沒有,則new一個Node,value=A[i],count=1,next = NULL;然后遍歷鏈表,如果鏈表中的節(jié)點this->count > n/2,則輸出this->value;否則輸出-1評估2 : 節(jié)省了大量數(shù)組表示的空間,空間復雜度為different(不同的元素數(shù)量)的節(jié)點空間.時間復雜度上(按比較次數(shù))為1+2+...+n-1 = n(n-1)/2,為O(n*n),復雜度還是太大.比較排序上可以優(yōu)化.解決辦法3 : 指針的數(shù)組表示int *C[n],將申明n個大小的數(shù)組,數(shù)組中的元素是指針,初始化指向A[i]對應的地址,也就是建立A[i]元素的索引,對索引進行排序(自底向上排序,基數(shù)排序等等),最壞情況下的比較次數(shù)為nlogn次,然后在遍歷一遍,對相同的值統(tǒng)計,輸出結果.評估3 : 對索引(C[n])進行交換操作,可以節(jié)省大量的實體賦值操作,節(jié)省大量的內存資源.(但是這是對于結構大的數(shù)據(jù)而言效果好,對于int的根本沒必要)解決辦法4 : 直接對數(shù)組A進行排序,最壞比較次數(shù)為nlogn次,再遍歷一遍A,統(tǒng)計相同的數(shù)值的數(shù)量,輸出結果評估4 : 統(tǒng)計相同數(shù)值的數(shù)量,會統(tǒng)計到其他無用的計算,浪費資源.可以直接根據(jù)多數(shù)元素的定義,直接統(tǒng)計A[n/2]的值的數(shù)量解決辦法5 : 在辦法4上進行改進,直接統(tǒng)計A[n/2]的值的數(shù)量,兩端用二分法快速找出起始位置和終點位置,相減就是數(shù)量,跟n/2比較,輸出結果評估5 : 時間復雜度nlogn+logn,空間復雜度為n解決辦法6 : 不進行排序,直接找出中間元素mid,然后遍歷找出mid的數(shù)量評估6 : 時間復雜度為20n+n,更少.解決辦法7 : */
#include <iostream>
using namespace std;
template<class T>
int Size(T &array)
{return sizeof(array)/sizeof(array[0]);
}//方法1,遍歷數(shù)組A,找出多數(shù)元素
typedef struct Node
{int value;int count;Node * next;Node(int num):value(num),count(1),next(NULL){};Node():value(-1),count(-1),next(0){};
}* headnode,* lnode;class List
{headnode head;int n;
public:List():n(0){head = new Node();};~List(){deletelist(head);};bool find(int num); void addNode(int num);void increment(int num);int major_return();void deletelist(Node *p);
};void List::deletelist(Node *p)
{while (p->next){Node *temp = p->next;p->next = temp->next;delete temp;}delete p;}bool List::find(int num)
{n++;lnode pre;pre = head;while(pre != NULL && pre->value != num) {pre = pre->next;}if (pre == NULL){return false;}return true;
}void List::addNode(int num)
{lnode pre = head;lnode newnode = new Node(num);while(pre->next != NULL ) {pre = pre->next;}pre ->next = newnode;
}void List::increment(int num)
{lnode pre;pre = head;while(pre->value != num) {pre = pre->next;}pre ->count ++;
}int List::major_return()
{lnode pre;pre = head;int temp = n/2;while(pre != NULL) {if (pre -> count >= temp){return pre ->value;}pre = pre->next;}return -1;
}int Majority_first(int *array,int n)
{List headlist;int temp = 0;for (int i = 0; i < n; ++i){temp = array[i];if (headlist.find(temp)){headlist.increment(temp);}else{headlist.addNode(temp);}}return headlist.major_return();
}//方法2,刪除數(shù)組中任意兩個不同的元素,原數(shù)組的多數(shù)元素仍是新數(shù)組的多數(shù)元素
/*分析 : 每次遞歸調用,是先查找原數(shù)組中任意不相同的兩個數(shù)值(直接與當前數(shù)組最后一位進行比較,不同,則將不同的數(shù)值與倒數(shù)第二位對調,這里不用索引,因為索引指向的類型結構小,不適合)遞歸調用函數(shù)的形參表應是數(shù)組a,數(shù)量n.放回int.遞歸結束標志是1.比較中沒有不相同的數(shù) 2.只有一個元素(這種情況包含在1中) (默認有多數(shù)元素>n/2的情況下)這種情況得出的結果是候選值,還需要遍歷數(shù)組,找出數(shù)量.看書分析 : 方法2是每次刪除兩個不同元素.可以進行改進.
*/
int candidate(int *array,int num)
{if (num == 0)return -1;if (num == 1)return array[0];int last = array[num-1];int i = num - 2;for (; i >= 0 ; i-- ){if (array[i] != last)break;}if ( i == -1)return array[0];last = array[num - 2];array[num - 2] = array [i];array[i] = last;return candidate(array,num-2);
}//改進candidate,從頭遍歷,如果有一段為平衡數(shù)組(候選元素與其他元素數(shù)量相同),則從接下來再開始比較,節(jié)省遞歸調用的次數(shù)
int improve_candidate(int *array ,int num,int start)
{int j = start ;int temp = array[start] ;int count = 1;while (j < num && count > 0){j++ ;if (array[j] == temp){count++;}else{count--;}}if ( j == num)return temp;else return improve_candidate(array,num,j+1);}int Majority_second(int *array,int n)
{int can = improve_candidate(array,n,1);if (can == -1) return -1;int count = 0 ;for (int i = 0; i < n ; i++){if (array[i] == can){count ++;}}if (count > n/2)return can;return -1;
}//測試
int main(int argc, char const *argv[])
{int a[]={1,2,3,4,5,6,7,8,9,1,1,1,1,1,1,1,1};int n=Size(a);int ret = Majority_second(a,n);if (ret == -1){cout << "沒有多數(shù)元素";}else{cout << "多數(shù)元素為: "<<ret<<endl;}system("pause");return 0;
}
轉載于:https://www.cnblogs.com/jiangge3/articles/5981163.html
總結
- 上一篇: 原生js随笔
- 下一篇: MongoDB学习笔记(一:常见问题汇总