【筆試面試】2015華爲軟件開發實習生

時間: 2015.06.16
地點:廈門大學

  1. 簡單題: 10個數字位取3個組成一個三位數(不能重複),使得這三位數的值最大。
    方法:這個是送分題,我比較懶,直接用set 來存放,然後輸出後面三個位置的值來搞定

  2. 奇偶數排序問題
    問題描述: 一串無序的數字,先根據所以奇數的逆序排序,再輸出所有偶數的順序排序數值。
    方法: 很簡單,基本兩個排序就可以搞定。

  3. 最大的邊長問題:
    問題描述:大致是這樣子,有一個n*m的0 ,1 組成的矩陣,求該矩陣的最大的正方形子區域,使得正方形區域內的所有元素都爲1,並輸出改正方形的邊長。其中n,m<=400;

解法1:暴力解法:窮盡所有的正方形子區域(O(N^2))+判斷該正方形子區域內的元素是否都爲1(O(N^2)),所以該方法的時間複雜度是(O(N^4)),鑑於n,m<=400,改方法肯定不可取的。

解法N:
這種問題,一定要想方設法的避免重複計算問題,可以考慮以空間換時間的方式去實現。

想法1: 積分圖的方法://跟圖像上的積分圖一個概念。
僞代碼

1. 計算改n*m矩陣的積分圖,時間複雜度爲O(n*m);
2. 再窮舉所有的正方形子區域(O(n^2))
3. 計算該正方形區域的所有的元素和O(1)
4. 縱上改方法的時間複雜度爲O(n*n),鑑於n,m<=400,所以該方法的效率不算太低。

源代碼:

#include<iostream>
using namespace std;
int data[400][400];//原始數據
int ig[401][401];//積分圖

bool evaluate(int a,int b,int edge)
{
   int sum=(ig[a+edge][b+edge]-ig[a+edge][b]-ig[a][b+edge]+ig[a][b]);
   if(sum==(edge*edge))
    return true;
   else
    return false;
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        {
            cin>>data[i][j];
        }
    //計算積分圖
    for(int i=0;i<=n;i++)
    {
        ig[i][0]=0;
    }
    for(int j=0;j<=m;j++)
    {
        ig[0][j]=0;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            ig[i][j]=ig[i-1][j]+ig[i][j-1]-ig[i-1][j-1]+data[i-1][j-1];
        }
    }
    //計算所有可能的子正方形區域
    //子正方形區域內的元素如果都爲1,則其積分圖爲邊長的平方.
    int  max_edge=m>n?n:m;
    for(int edge=max_edge;edge>=1;edge--)
    {
    for(int i=0;i<=n-edge;i++)
      for(int j=0;j<=m-edge;j++)
      {
         if(evaluate(i,j,edge))
         {
            cout<<edge<<endl;
            return 0;
         }
      }
    }
    //
    cout<<0<<endl;
    return 0;
}

可惜當時做的時候,沒有想到這個,只是在考完回來的路上纔想到的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章