1. 程式人生 > >程式設計題:(一)數字規律

程式設計題:(一)數字規律

(一)陣列中出現次數超過一半的數字(如果不存在則輸出0)

    假設不會出現0超過一半的情況;若有可以設定一個全域性的bool變數來檢查。

 (1)解法一:利用map;鍵值為陣列中元素值,關聯值為數出現的次數

int MoreThanHalfNum_Solution(vector<int> numbers)
    {
        int len=numbers.size();
        map<int,int> ma;
        if(len==0)
            return 0;
        for(int i=0;i<len;i++)
            ++ma[numbers[i]];
        for(map<int,int>::iterator mapIte=ma.begin();mapIte!=ma.end();mapIte++)
        {
            if(mapIte->second>len/2)
                return mapIte->first;
                
        }
        return 0;
    }

(2)解法二:

   思路:因為陣列中有一個數字出現的次數超過陣列長度的一半,也就是說出現的次數比其它所有數字出現的次數的和還要多。因此可以儲存兩個值:一個數組中的數字,一個是次數。遍歷陣列,如果陣列中的下一個數字與之前儲存的數字相同則次數加1;如果不同則次數減1;如果次數為0,則儲存下一個數字並把次數設為1.最後一次把次數設為1的數字即為對應的數字。

int MoreThanHalfNum_Solution(vector<int> numbers)
    {
        int len=numbers.size();
        if(len==0)
            return 0;
        //兩兩比較最後一個使times變為1的即為要找的數
        int times=1;
        int result=numbers[0];
        for(int i=1;i<len;i++)
        {
            if(times==0)//如果次數為0,則將次數設為1,並儲存當前的數字
            {
                times=1;
                result=numbers[i];
            }
            else
            {
               if(numbers[i]==numbers[i-1])
               {
                   times++;
                   result=numbers[i];
               }
                else
               {
                  times--;
               }
            }
        }
        //檢查result是否超過一半
        times=0;
        for(int i=0;i<len;i++)
        {
            if(numbers[i]==result)
                times++;
        }
        if(times<=len/2)
            result=0;
        return result;
    }

(二)陣列中最小的K個數

  方法一:利用  大頂堆,堆初始化為陣列前k個元素。然後將陣列中剩下的元素與堆中最大值進行比較,若比堆中最大值小則進行替換。自己實現堆太複雜,可以利用STL中的set來模擬;set底層利用紅黑樹來實現,set會自動排序,因此可以以O(1)時間找出最大值;紅黑樹的插入和刪除操作都只需要O(logk)時間。

vector<int> GetLeastNumbers_Solution(vector<int> input, int k) 
    {
        vector<int> vec;
        int len=input.size();
        if(len<k||k<=0)
            return vec;
        multiset<int> intSet(input.begin(),input.begin()+k);//初始化intSet中為vector中前k個數
        for(int i=k-1;i<len;i++)
        {
            if(input[i]<*(intSet.rbegin()))//判斷是否小於intSet中的最大值,若小於則進行替換
             {
                intSet.erase(*(intSet.rbegin()));//set的迭代器是const的不能直接賦值,set不支援遞減操作
                intSet.insert(input[i]);//因此只能使用反向迭代器來獲取最後一個值。或者定義時指定set為降序,獲取第一個值
             }
            
        }
        for(multiset<int>::iterator iteSet=intSet.begin();iteSet!=intSet.end();iteSet++)
        {
            vec.push_back((*iteSet));
        }
        return vec;
    }

      方法二:可以借鑑快排的思想。快排每次排序會使第n個元素,排在第n位;因此利用快排的思想,當第k個元素在第k位時,前k個元素即為最小的k個。(缺點是:不適合於大資料處理)

(三)連續子陣列的最大和

    思路:如果第k個數之前累加的和是負數,則加上第k個數後的值肯定小於等於第k個數,因此:若之前累加的和是負數則用當前值覆蓋之前值。如果之前的累加值大於0,則繼續累加。若加上第k個數後累加值大於之前的,則更新累加的最大值。

int FindGreatestSumOfSubArray(vector<int> array) 
    {
        int greatSum=0x80000000;
        int len=array.size();
        if(len==0)
            return 0;
        int currentSum=0;
        for(int i=0;i<len;i++)
        {
            if(currentSum<0)
                 currentSum=array[i];
            else
                currentSum+=array[i];
            if(currentSum>greatSum)
                greatSum=currentSum;
                                
        }
        return greatSum; 
    }

(四)一個整型數組裡除了兩個數字之外,其他的數字都出現了兩次。找出這兩個只出現一次的數字。

思路:兩個相同的數異或為0;0與任何數異或仍然是該數。總體思路將這兩個只出現一次的數分為兩組,然後分別對每一組進行異或。因為兩個不同的數的二進位制至少有一位不同即:異或後至少有一位為1;根據異或後第一個為1的位將原陣列分成兩個陣列,即可以將兩個值出現一次的數分到兩個數組裡。再分別對兩個陣列異或即可。

void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) 
    {
       int len=data.size();
       if(len<2)
            return;
       int tempNum=0; 
       for(int i=0;i<len;i++)
           tempNum^=data[i];//找出兩個數中不同的位
       int flag=1;
       while(!(flag&tempNum))//找出第一個不同的位
            flag=flag<<1;  
        *num1=0;
        *num2=0;
        for(int i=0;i<len;i++)//根據不同的位將陣列分成兩組,分別異或,得到結果
        {
            if((flag&data[i])==0)//==的優先順序高於&
                *num1^=data[i];
            else
               *num2^=data[i];             
        }        
    }

(五)一個整型陣列有一個數只出現1次,其它數都出現3次,求這個數

    思路:對各個數進行二進位制位加和;若某位上二進位制上1的個數為3的倍數,則該數的在該位上的二進位制位0;若某位上的1的個數不是3的倍數,則該數在該位上的二進位制位1。

(六)1001個數字,1~1000中有一個出現兩次,其餘都出現一次

    (1^2^3…..^1000)^(a[0]^a[1]^…..a[1000])

(七)尋找陣列中最大值和最小值

方法一:N中的每個數分別和max,min比較,大於max的就不必和min比較,小於min的也不必和max比較。因此比較的次數不足2N次

方法二:陣列中的一對一對的數相互比較,比較中較大的一個和max比較,較小的和min比較,總計有N/2對數,分別和max和min進行一次比較,共計3N/2次比較

方法三:兩個數為1組,將大的放在偶數位,小的放在基數位。然後在偶數位找大的,基數為找小的。

方法四:分治策略:分別求出前後N/2個數的min和max,然後,取較小的min,較大的max即可。

(八)找出N個數中的第二大數

   思路:用兩個變數分別存最大值max和次大值secondMax,遍歷陣列:如果arr[i] > max,則更新secondMax=max,max=arr[i];否則如果arr[i] > secondMax,則更新secondMax=arr[i];否則,不進行更新操作。

這個方法最多的比較次數為2*N次,最小N次。

int secondMaxNum(int num[],int length)
{
	assert(num!=NULL&&length>=2);
	int max=num[0];//不能為0,因為陣列中可能全為負數
	int secondMax=num[1];//不能為num[0],否則若陣列第一個為最大時,則secondMax無法更新
	for(int i=0;i<length;i++)
	{
		if(num[i]>max)
		{
			secondMax=max;
			max=num[i];
		}
		else if(num[i]>secondMax&&num[i]<max)
			secondMax=num[i];

	}
	return secondMax;
	
}

(九)找出連結串列中第二大和第二小的數

   思路:定義是個變數:最大,次大,最小,次小。每個數可能有五個區間(畫個橫座標好分析);對五個區間進行判斷,一遍掃描既可判斷

(十)100個整數中取出一個,怎麼判斷取出的是哪個(CVTE)

方法一:把取之前所有的數加和再減去取之後的數即可得到。(可能會越界)

方法二:把取之前的與取之後的合成一個數組,然後排序。再遍歷一遍即可找到。(對於取出2個的情況也適用)

方法三:先把100個數排序,再把99個排序,然後一一對比。(對於取走多個數的情況也適用)

方法四:對100個數建一個hash表,再一個個找,沒有找見的即為刪除的。

(十一)兩個32位整數m,n的二進位制中有多少位不同

   方法一:兩個數異或得到的數的二進位制中1的個數即為不同的位的個數。二進位制中1的個數:一個數與自己減1相與,統計的即是這個數最右邊為1的位。

int getDifference(int const m,int const n)
{
	int differenceNum=m^n;
	int count=0;
	while(differenceNum)
	{
          differenceNum=differenceNum&(differenceNum-1);
	  ++count;
	}
	return count;
}

   方法二:分別兩個數的二進位制表示的每一位使1還是0;然後對每一位進行異或。

int getDifference(int const m,int const n)
{
	int count=0;
	int flag=1;
	while(flag)
	{
           if((flag&m)^(flag&n))//分別求出每一位為1還是0,再進行異或
	   ++count;
	 flag<<=1;
	}
	return count;
}


(十二)n!末尾的0的個數

   思路:因為只有一個偶數乘以5的倍數才會產生10,因為偶數的個數比5的因子個數多,因此統計小於n的數中5的因子的個數即可。注意25提供兩個5......

   方法一:統計每個數中可以提供的5的因子個數

int last0Num(int n)
{
	int count=0;
	for (int i=1;i<=n;i++)
	{
		int j=i;
		while(j%5==0)
		{
			count++;
			j=j/5;
		}
	}
	return count;
}

方法二:統計不大於n的數中5的倍數,25的倍數,125倍數....分別有多少

int last0Num(int n)
{
	int count=0;
	while(n)
	{
		count+=n/5;
		n=n/5;
	}
	return count;
}

相關推薦

程式設計數字規律

(一)陣列中出現次數超過一半的數字(如果不存在則輸出0)     假設不會出現0超過一半的情況;若有可以設定一個全域性的bool變數來檢查。  (1)解法一:利用map;鍵值為陣列中元素值,關聯值為數出現的次數 int MoreThanHalfNum_Solution(

併發程式設計學習java併發程式設計的藝術

一: 1.併發與並行:併發是多個執行緒(任務)共同爭奪一個cpu進行處理,並行是多個cpu各自處理對應的執行緒任務,現階段都只是併發而不是真正意義上的並行。 2.上下文切換:      即使單行處理器也支援多執行緒執行任務,cpu通過給每個執行緒分配cpu時

LeetCode 刷指南為什麼要刷

雖然刷題一直飽受詬病,不過不可否認刷題確實能鍛鍊我們的程式設計能力,相信每個認真刷題的人都會有體會。現在提供線上程式設計評測的平臺有很多,比較有名的有 hihocoder,LintCode,以及這裡我們關注的 LeetCode。 程式碼提交曲線 LeetCode

【如何自學程式設計系列】如何做到無師自通?

無數莘莘學子為了理想,進行著他鄉求知的旅途。求學生活你要怎麼渡過呢?你是要先享受來之不易的求學生活呢還是繼續為人生目標而奮鬥。閒言少敘,當今社會一步拉下很有可能步步落後。得有憂患意識。誰也不想上完大學結果被大學給上了,畢業季很有可能就是失業季。 每個人都有自己的理想和人生目標,程式設計也

【怎樣寫程式碼】函數語言程式設計 -- Lambda表示式引出

如果喜歡這裡的內容,你能夠給我最大的幫助就是轉發,告訴你的朋友,鼓勵他們一起來學習。 If you like the content here, you can give me the greatest help is forwarding, tell you

雲平臺程式設計與開發Java雲平臺服務商一覽

因為Java語言的跨平臺性和高度靈活性,成為目前雲端計算平臺的主流開發語言;所以,這裡重點討論一下Java 雲平臺的比較情況。尤其是討論X5Cloud雲平臺與現有幾個Java雲平臺的聯絡和區別:      * App Engine (http://code.google.com/appengine/)    

程式設計與數學計算玩家面對面

最近聽到這樣一個需求,VR多人遊戲的時候,當兩個玩家面對面的情況下,才可以開始下一個流程: 聽到一個人的解決方案是算距離,具體沒問,覺得略感複雜,趁此機會也發揮程式與數學的相關性一直很強,從此篇開始會專門寫一些程式與數學應用的部落格。 好了切入正題,每個角色

Re從0開始的微服務架構重識微服務架構--轉

相關 推廣 模塊劃分 ati 滿足 face jar 點擊放大 積累 原文地址:http://www.infoq.com/cn/articles/micro-service-architecture-from-zero?utm_source=infoq&utm_me

linux經典

awk   grep   sed1.1創建一個目錄/data。1) 解答: mkdir /data擴展:mkdir後面可以加參數-p,表示遞歸創建,也可以加參數-v,表示可以顯示出創建的過程。1.2為oldboy.txt增加內容為“I am studying linux.”。解答:為文

前端開發規範手冊基本原則

name ges rop scrip 有效 object sel 代碼 charset 1、結構、樣式、行為分離 盡量確保文檔和模版只包含HTML結構,樣式都放到樣式表中,行為都放到腳本裏。 2、縮進 統一兩個空格縮進(總之縮進統一即可),不要使用Tab鍵或者Tab

JVM學習筆記數字在JVM中的表示

oat 技術 3-9 cnblogs es2017 ext ava bsp eee 數字在JVM中的表示 一、整數在JVM中的表示 1.在Java虛擬機中,整數有四種表示: byte:8位 short:16位 int:32位 long:64位

【微服務從入門到精通】微服務的藍綠發布及灰度發布

采樣 前端 入門 後端 blog 文件 風險 性能 切換 藍綠部署 基本上,藍綠部署是一種以可預測的方式發布應用的技術,目的是減少發布過程中服務停止的時間。 簡單來說,你需要準備兩個相同的環境(基礎架構),在藍色環境運行當前生產環境中的應用,也就是舊版本應用,如圖中 A

從0開始的微服務架構重識微服務架構

拆分 dock try 快速入門 比較 資源 貼吧 升級維護 頁面 導語 雖然已經紅了很久,但是“微服務架構”正變得越來越重要,也將繼續火下去。 各個公司與技術人員都在分享微服務架構的相關知識與實踐經驗,但我們發現,目前網上的這些相關文章中,要麽上來就是很有借鑒意義的幹貨,

python3學習筆記——數字、字符串、列表、字典、元組

類型 單詞 nbsp 3.1 true expand 替換 割點 gpo 什麽是python解釋器?

深入理解JVM虛擬機Java運行時數據區域

字面量 符號 地方 64位 因此 lower 優化 java堆大小 工作 概述 JVM是Java語言的精髓所在,因為它Java語言實現了跨平臺運行,以及自動內存管理機制等,本文將從概念上介紹JVM內存的各個區域,說明個區域的作用。 JVM運行時數據區模型 Java虛擬機在執

eureka服務註冊與發現搭建註冊中心

hostname dubbo efault 必須 技術分享 不存在 dea bsp 啟用 最近由於工作中需要將原來的spring項目都進行架構調整,要實現應用解耦,所以考慮到通過微服務的方式將應用解耦。所以面臨兩個選擇:dubbo 和spring cloud ,由於項目規模

日常代碼優化系列獲取url參數

分別是 對象 https 結果 font 被調用 undefined span repl 最近刷牛客網的時候,看到某大神寫的 獲取url參數 的簡潔寫法,正則用的那叫一個6,頓時心生敬佩,趕緊來學習膜拜一下~~ 題目描述:獲取 url 中的參數 1. 指定參數名稱,返回該

Android 開發安卓開發環境搭建與配置 (Windows和Mac )以及目錄結構介紹

(一)、windows版 一. 開發工具: 1.Android Studio:(http://www.androiddevtools.cn/) 2.Genymotion(虛擬機器):(http://www.genymotion.net/) (二)、Mac版 一

PL/SQL程式設計基礎知識

--PL/SQL變數的宣告和賦值 declare v_ename varchar2(30);--定義變數 begin v_ename:='&請輸入名字';--接受鍵盤輸入 dbms_output.put_line(v_ename); end; --put_line :列印換行

zuulSpringCloud的閘道器介紹和zuul閘道器的使用

1)什麼是閘道器?         API Gateway,是系統的唯一對外的入口,介於客戶端和伺服器端之間的中間層,處理非業務功能 提供路由請求、鑑權、監控、快取、限流等功能 統一接入 智慧路由