金山辦公2020校招C++開發工程師筆試題(一)

鏈接:https://www.nowcoder.com/test/21499425/summary

11、框選線段

在二維平面座標系中,已知存在一條線段(圖中P1->p2)和一個矩形區域,編程計算得出線段被矩形區域裁剪的新起始點。

注意以下要求:

A、線段是有方向的,裁剪得到的新線段也需要保持原線段的方向;下圖中,線段的描述是P1->p2,則裁剪的結果是P3->p4,反之,如果線段描述是P2->P1,則結果是P4->P3
B、線段的起始點在矩形區域裏面時,裁剪的結果則就是原始線段
C、當線段與矩形區域沒有相交線段的時候,結果輸出“-1”

#include <iostream>
using namespace std;
struct Point {
    float x, y;
};
struct Rect {
    Point leftBottom, rightTop;
    bool contain(const Point& pt) {
        return pt.x > leftBottom.x&& pt.x<rightTop.x && pt.y>leftBottom.y&& pt.y < rightTop.y;
    }
    void cut(Point& pt, const Point& dir) {       //根據方向向量將點裁剪到矩形上
        if (contain(pt))                       //如果點在矩形內,則不需要對它裁剪
            return;
        Point offset = { 1,dir.y / dir.x };      //確定水平方向,計算垂直方向的偏移
        if (pt.x > rightTop.x)
            pt = { rightTop.x,pt.y + offset.y * (rightTop.x - pt.x) };
        else if (pt.x < leftBottom.x)
            pt = { leftBottom.x,pt.y + offset.y * (leftBottom.x - pt.x) };
        offset = { dir.x / dir.y,1 };         //確定垂直方向,計算水平方向的偏移
        if (pt.y > rightTop.y)
            pt = { pt.x + offset.x * (rightTop.y - pt.y), rightTop.y };
        else if (pt.y < leftBottom.y)
            pt = { pt.x + offset.x * (leftBottom.y - pt.y), leftBottom.y };
    }
};
 
istream& operator>>(istream& in, Point& pt) {
    in >> pt.x >> pt.y;
    return in;
}
 
int main() {
    Rect rect;
    Point p1, p2;
    Point dir;  //直線的方向向量
 
    cin >> rect.leftBottom >> rect.rightTop;
    cin >> p1 >> p2;
    dir = { p2.x - p1.x,p2.y - p1.y };
    rect.cut(p1, dir);
    rect.cut(p2, dir);
    if (p1.x == p2.x && p1.y == p2.y)
        printf("-1");
    else
        printf("(%0.2f,%0.2f)\n(%0.2f,%0.2f)", p1.x, p1.y, p2.x, p2.y);
    return 0;
}

12、最短路徑字符串

給定一個M行N列表格,從左上角單元格開始,每次只能向右或者向下走,最後到達右下角單元格位置,路徑上所有單元格內字符串拼接起來就是路徑字符串,求所有路徑中路徑字符串字符長度最短的路徑字符串的長度。

如給定3行4列表格(m=3,n=4),各單元格字符串內容如下表所示,那麼表中箭頭所指的路徑(灰色背景單元格)即爲最短路徑,對應的內容爲粗斜體字符串即“武漢金山辦公公司”長度爲8,最終的結果也就是這個字符串。

要求:

輸入:strTableContent爲表格字符串表示,使用“|”作爲單元格分隔符,“/”作爲表格行分隔符,將表格從左向右,從上向下依次序列化,如下標的字符串表示爲:
strTableContent=”武漢|金山|辦公|/金山辦公|辦|軟件|有限/軟件有限公司|公||公司/”;

輸出:GetMinPathStringLength 返回結果爲”8”;

img

 

輸入例子1:

3,4,"wh|js|bg|/jsbg|b|rj|yx/rjyxgs|g||gs/"

輸出例子1:

8

例子說明1:


 

 

#include <iostream>
#include <vector>
#include <string>
#include <limits>
#include <algorithm>
using namespace std;

class Solution {
public:
	int GetMinPathStringLength(int m, int n, string strTableContent) {
		vector<vector<int>> graph;
		int minSize = numeric_limits<int>::max();
		int count = 0;
		vector<int> row;
		for (char& ch : strTableContent) {
			if (ch == '|') {
				row.push_back(count);
				count = 0;
			}
			else if (ch == '/') {
				row.push_back(count);
				count = 0;
				graph.push_back(row);
				row.clear();
			}
			else
				count++;
		}
		vector<vector<int>> dp(m ,vector<int>(n));
		dp[0][0] = graph[0][0];
		for (int i = 1; i < m; i++)
			dp[i][0] = graph[i][0] + dp[i - 1][0];
		for (int i = 1; i < n; i++)
			dp[0][i] = graph[0][i] + dp[0][i - 1];
		for (int i = 1; i < m; i++) {
			for (int j = 1; j < n; j++) {
				dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + graph[i][j];
			}
		}
		return dp[m-1][n-1];
	}
};

int main() {
	Solution s;
	s.GetMinPathStringLength(3, 4, "wh|js|bg|/jsbg|b|rj|yx/rjyxgs|g||gs/");
}

 13、字符串聯想

字符串聯想是一個被廣泛用於搜索引擎/輸入法的功能。聯想算法根據一定規則,計算出與待匹配字符串最接近的若干個聯想結果。聰明的ttt覺得這功能很好,希望剛入職的lhy也實現一個簡單的聯想算法。

ttt:客戶端將提供一個最優匹配結果數k,一個待匹配字符串,和若干個命令。希望你能實現一個算法,它實現兩種操作:
A: 增加一項搜索記錄
 P: 打印當前的k個最優匹配結果

我們規定每個匹配記錄(record)需滿足:record中存在至少一個與s完全匹配的子串。
並規定,若滿足下列條件,則稱record a是比record b更好的匹配記錄
1.record a長度短於record b

2.長度相同,record a的字典序小於record b

這可把熱愛摸魚的lhy難倒了。爲了幫lhy保住工作,和ttt一樣聰明的你能幫幫lhy嗎?

輸入描述:

輸入數據包含n + 3行每一組數據由三行組成

第一行:n

第二行:k

第三行:s

第四行~n+3行:

[A record] 或 [P]

n: 需執行的總命令數 (n < 10000)k:需要輸出的總匹配記錄數目(0 <k <= n)s:待匹配字符串 (0 < length < 100)A record: 增加一項record, 記錄和A由空格分隔P: 打印當前的k個最優匹配結果

輸入數據保證每條字符串長度 (0 < length < 100),且僅由小寫ANSI字符組成

輸出描述:

每次P命令執行後,輸出

P:

k行數據(不允許有重複數據,相同的看做同一條數據)。

不足k行則輸出所有符合題幹條件的記錄。

輸出順序需按提幹條件由優先級高->低順序排列

輸入例子1:

6
3
wps
A ttt.smart
A lhy.stupid.wps
P
A lhy.stupid.wps
A wps.cn
P

輸出例子1:

P:
lhy.stupid.wps
P:
wps.cn
lhy.stupid.wps

輸入例子2:

4
1
ttt
P
A tttnba
A ttttql
P

輸出例子2:

P:
P:
tttnba
#include <iostream>
#include <string>
#include <regex>
#include <set>
using namespace std;
struct cmp{
	bool operator()(const string& a,const string& b) const {
		return a.size() != b.size() ? a.size() < b.size() : a < b;
	}
};
int main() {
	int n, k;
	string str,record;
	char type;
	set<string, cmp> match;
	cin >> n >> k >> str;
	for (int i = 0; i < n; i++) {
		cin >> type;
		if (type == 'A') {
			cin >> record;
			if(regex_search(record, regex(str)))
				match.insert(record);
		}
		else {
			
			cout << "P:" << endl;
			int output = 0;
			for (const string& s : match) {
				cout << s << endl;
				if (++output==k)
					break;
			}
		}
	}
	return 0;
}

14、遍歷二叉樹

某地主擔心農民偷取他的糧食,僱人挖了大量地窖來屯糧,這些地窖層層排列,只有一個總入口。 每個地窖都有一個隨機且唯一的數字編號(1 ... N)。聰明的農夫經過一番偵察,發現所有的地窖形成了一顆滿二叉樹,只有葉子節點中才存放有糧食,糧食數量與地窖編號相同。 狡猾的地主設置了報警裝置,只要任意兩個相鄰的葉子節點中糧食被偷,就會自動報警。
農夫事先並不知道地窖分佈圖,但是他無意間得到了地窖組成的二叉樹的前序遍歷和中序遍歷結果,請幫忙計算一下,在不觸發報警裝置的情況下,農夫最多可以偷取地主多少糧食。
提示:

  1. 如果一個二叉樹的層數爲K,且節點總數是2k -1 ,則它就是滿二叉樹,如下圖所示。
  2. 下圖中節點1和節點2,節點2和節點3均爲相鄰的葉子節點, 節點1和節點3不屬於相鄰葉子節點;

輸入描述:

第一行輸入一個數字n表示有n個節點的滿二叉樹

第二行n個數字a[0],a[1]...a[n-1]用空格隔開,表示二叉樹的前序遍歷

第三行n個數字b[0],b[1]...b[n-1]用空格隔開,表示二叉樹的中序遍歷

數據範圍:

3<=n<=105 且n可以表示成2k-1(k爲整數)

a[0]...a[n-1]中1,2...n每個數字分別出現一次

b[0]...b[n-1]中1,2...n每個數字分別出現一次

輸出描述:

輸出一個數字,表示農夫最多可以偷取地主多少糧食

輸入例子1:

3
2 1 3
1 2 3

輸出例子1:

3
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<int> getLeavesByPreOrder(const int& n, int i = 0) {    //根據前序遍歷確定葉節點
    static vector<int> leaves;
    int temp;
    cin >> temp;
    if ((i << 1) + 1 >= n) {                               //添加葉節點
        leaves.push_back(temp);
        return leaves;
    }
    getLeavesByPreOrder(n, (i << 1) + 1);
    getLeavesByPreOrder(n, (i << 1) + 2);
    return leaves;
}
int main() {
    int n;
    cin >> n;
    vector<int> leaves = getLeavesByPreOrder(n);
    vector<int> dp(leaves.size());
    dp[0] = leaves[0];
    dp[1] = max(leaves[0], leaves[1]);
    for (int i = 2; i < dp.size(); i++)
        dp[i] = max(dp[i - 2] + leaves[i], dp[i - 1]);
    cout << dp.back();
    return 0;
}

 

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