2019美團機器學習/數據挖掘算法實習生筆試 編程題修改矩陣

主要用於交流思考

1.修改矩陣

時間限制:C/C++語言 1000MS;其他語言 3000MS
內存限制:C/C++語言 65536KB;其他語言 589824KB題目描述:
我們稱一個矩陣爲黑白矩陣,當且僅當對於該矩陣中每一個位置如(i,j),其上下左右四個方向的數字相等,即(i-1,j),(i+1,j),(i,j+1),(i,j-1)四個位置上的數字兩兩相等且均不等於(i,j)位置上的數字。(超出邊界的格子忽略)
現在給出一個n*m的矩陣,我們想通過修改其中的某些數字,使得該矩陣成爲黑白矩陣,問最少修改多少個數字。
輸入
第一行包含兩個整數n,m,表示矩陣的長寬。(1≤n,m≤100000,1≤n*m≤100000)。
接下來有n行,每行包含m個整數,中間用空格隔開,表示n*m的矩陣。
輸出
輸出僅包含一個數字,表示該矩陣想修改爲黑白矩陣最少修改的數字數量。

樣例輸入
3 3
1 1 1
1 1 1
1 1 1
樣例輸出
4
提示
補充樣例
輸入樣例2
3 3
1 1 1
1 5 1
1 1 1
輸出樣例2
4

我的思路:
題中說n行m列,按照我個人習慣,顛倒了一下
直接用暴力去解。行m,列n
1.從第0行開始,將該行的每個值逐個交替的存入字典a,b,鍵爲該值,值爲該值出現的次數。
若是偶數行(索引從0開始),則存入順序爲字典a,b;否則爲b,a.且最終a中值的總和與b中值的總和總是差1,且總和爲m*n
2.將字典按照值逆序排序,也就是出現次數多的鍵排在前面。
3.兩個for循環(本來以爲很耗時,其實還行)逐個比較目前出現次數最大的鍵。
4.如果兩個鍵不同,修改的次數,直接以m*n-v(k1)-v(k2)來計算。意思是,鍵不同且目前出現次數爲最高,只需要將剩餘不同的鍵分別修改爲當前鍵即可。
例如:

1 3 1 
3 1 3
1 1 3

在該矩陣中,字典a爲:{'1':4,'3':1},字典b爲{'3':3,'1':1}。按照我的思路來說,即出現次數最高的鍵不同,則只需將a中不爲1的鍵修改爲1,b中不爲3的值修改爲3。即最少修改次數是3*3-4-3=2。直接返回。
5.如果出現次數最高的鍵相同,則比較出現次數,此時考慮6,7兩種情況。
6.此時該矩陣中僅有一個數字,例如全1,此時做比較的兩個出現次數值的和即爲m*n,那麼將出現次數較小的值記爲修改次數。參考樣例1
7.此時該矩陣中有兩個及上數字,比較v(k1)和v(k2),保留當前較大值,取另一組的次大值,循環4-7。

求批評指正,修改

代碼:

# m,n
# matrix1 raw col
# a_dict
# b_dict
# num

"""
該段爲題目中的標準輸入,每行讀取,並存入矩陣
"""
m,n = map(int ,input().split(' '))
matrix = []
raw = []
for i in range(m):
    raw = [x for x in input().split(' ')]
    matrix.append(raw)

#print(m,n)
#print(matrix)

# i=(0,0) or i=(0,1)
a_dict = {}
b_dict = {}

"""
該段爲測試,建立隨機數大矩陣,和元矩陣。
並記錄不同過程的時間
"""
import numpy as np
import time

matrix = np.random.randint(0,10,size=[1,100000])
#matrix = np.ones((1000,100))

m = 1
n =100000
"""
該段爲字典更新,其中以行爲外循環,列以每2步一個循環,每次確保不越界。
交叉存儲a,b。
"""
m1 = time.time()
for i in range(m):
    if i%2==0:
        for j in range(0,n,2):
            a_dict[matrix[i][j]] = a_dict.get(matrix[i][j],0)+1
            if j+1< n:
                b_dict[matrix[i][j+1]] = b_dict.get(matrix[i][j+1],0)+1 
    else:
        for j in range(0,n,2):
            b_dict[matrix[i][j]] = b_dict.get(matrix[i][j],0)+1
            if j+1 < n:
                a_dict[matrix[i][j+1]] = a_dict.get(matrix[i][j+1],0)+1

m2 = time.time()
"""
該段爲字典排序,此處需要注意是,排序後是一個列表
"""
a_dict = sorted(a_dict.items(),key=lambda item:item[1],reverse=True)
#print(a_dict)
b_dict = sorted(b_dict.items(),key=lambda item:item[1],reverse=True)
#print(b_dict)
"""
該段是計算修改次數。思路如上
"""
m3 = time.time()
def compute_result(a_dict,b_dict):
    result = 0
    for a in a_dict:
        for b in b_dict:
            if a[0]!=b[0]:
                result = (m*n)-a[1]-b[1]
                return result
            else:
                if a[1]>=b[1]:
                    result = b[1]
                    continue
                else:
                    result = a[1]
                    break
    return result

print(compute_result(b_dict,a_dict))
m4 = time.time()

print(m2-m1)
print(m3-m2)
print(m4-m3)

我自己測試的樣例保存題目給出的,以及使用numpy隨機創建的。由於題目中限定(1≤n,m≤100000,1≤n*m≤100000),我在創建隨機矩陣測試時,使用了shape爲(100000,1)和(10000,10)和(1000,100)的矩陣,時間均不超過1秒。

┗|`O′|┛ 嗷~~!!該刷題了。

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