程序员面试金典84题之每日7题 - 第六天

第一题:平分的直线

题目:

在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分。假定正方形的上下两条边与x轴平行。

给定两个vecotrA和B,分别为两个正方形的四个顶点。请返回一个vector,代表所求的平分直线的斜率和截距,保证斜率存在。

测试样例:

[(0,0),(0,1),(1,1),(1,0)],[(1,0),(1,1),(2,0),(2,1)]
返回:[0.0,0.5]

解析:

平分正方形的直线必定经过正方形的中心

struct Point {
	int x;
	int y;
	Point() :
			x(0), y(0) {
	}
	Point(int xx, int yy) {
		x = xx;
		y = yy;
	}
};
class Bipartition {
public:
	vector<double> getBipartition(vector<Point> A, vector<Point> B) {
		// write code here
		double ax = A[1].x != A[2].x ? (A[1].x + A[2].x) / 2 : (A[0].x + A[2].x) / 2;
		double ay = A[0].y != A[1].y ? (A[0].y + A[1].y) / 2 : (A[0].y + A[2].y) / 2;
		double bx = B[1].x != B[2].x ? (B[1].x + B[2].x) / 2 : (B[0].x + B[2].x) / 2;
		double by = B[0].y != B[1].y ? (B[0].y + B[1].y) / 2 : (B[0].y + B[2].y) / 2;
		double k = (by - ay) / (bx - ax);
		double b = by - k * bx;
		return { k,b };
 	}
};

第二题:穿点最多的直线

题目:

在二维平面上,有一些点,请找出经过点数最多的那条线。

给定一个点集vectorp和点集的大小n,没有两个点的横坐标相等的情况,请返回一个vector,代表经过点数最多的那条直线的斜率和截距。

解析:

每两个点两辆组合求k和b,用哈希计数

struct Point {
	int x;
	int y;
	Point() :
			x(0), y(0) {
	}
	Point(int xx, int yy) {
		x = xx;
		y = yy;
	}
};
class DenseLine {
public:
	vector<double> getLine(vector<Point> p, int n) {
		// write code here
		map<pair<double, double>, int> hash;
		for (int i = 0; i < n - 1; ++i) {
			for (int j = i + 1; j < n; ++j) {
				double k = (p[j].y - p[i].y) / (p[j].x - p[i].x);
				double b = p[j].y - k * p[j].x;
				auto tmp = make_pair(k, b);
				++hash[tmp];
			}
		}
		vector<double> res(2);
		int max = 0;
		for (auto it = hash.begin(); it != hash.end(); ++it) {
			if (it->second > max) {
				max = it->second;
				pair<double, double> tmp = it->first;
				res[0] = tmp.first;
				res[1] = tmp.second;
			}
		}
		return res;
	}
};

第三题:第k个数

题目:

有一些数的素因子只有3、5、7,请设计一个算法,找出其中的第k个数。

给定一个数int k,请返回第k个数。保证k小于等于100。

测试样例:

3
返回:7

解析:

class KthNumber {
public:
	int findKth(int k) {
		// write code here
		int now = 3;
		vector<int> res;
		res.push_back(3);
		res.push_back(5);
		res.push_back(7);
		int last = 0;
		while (res.size() <= k) {
			last = res[res.size() - 1];
			for (int i = 0; i < res.size(); ++i) {
				if (res[i] * 3 > last) {
					if (now <= last) {
						now = res[i] * 3;
					}
					else
					{
						now = now < res[i] * 3 ? now : res[i] * 3;
					}
					if (now < res[i] * 3) break;
				}
				if (res[i] * 5 > last) {
					if (now <= last) {
						now = res[i] * 5;
					}
					else
					{
						now = now < res[i] * 5 ? now : res[i] * 5;
					}
				}
				if (res[i] * 7 > last) {
					if (now <= last) {
						now = res[i] * 7;
					}
					else
					{
						now = now < res[i] * 7 ? now : res[i] * 7;
					}
				}
			}
			res.push_back(now);
		}
		return res[k - 1];
	}
};

第四题:上楼梯

题目:

有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶、3阶。请实现一个方法,计算小孩有多少种上楼的方式。为了防止溢出,请将结果Mod
1000000007

给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。

测试样例1:

1
返回:1

测试样例2:

3
返回:4

测试样例3:

4
返回:7

解析:

1、递归
2、动态规划
注意:%1000000007的使用

class GoUpstairs {
public:
	int countWays(int n) {
		// write code here
		if (n == 1) return 1;
		if (n == 2) return 2;
		if (n == 3) return 4;
		int last3 = 1;
		int last2 = 2;
		int last1 = 4;
		int now = 0;
		for (int i = 4; i <= n; ++i) {
			now = ((last1 + last2) % 1000000007 + last3) % 1000000007;
			last3 = last2;
			last2 = last1;
			last1 = now;
		}
		return now;
	}
};

第五题:机器人走方格I

题目:

有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。

给定两个正整数int x,int y,请返回机器人的走法数目。保证x+y小于等于12。

测试样例:

2,2
返回:2

解析:

注意: dp[0][j]dp[i][0] 等于1

class Robot {
public:
    int countWays(int x, int y) {
        // write code here
        int dp[12][12];
        for(int i=0;i<x;i++){
            for(int j=0;j<y;j++){
                if(i==0)
                    dp[i][j]=1;
                else if(j==0)
                    dp[i][j]=1;
                else
                    dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[x-1][y-1];
    }
};

第六题:机器人走方格II

题目:

有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。注意这次的网格中有些障碍点是不能走的。

给定一个int[][] map(C++ 中为vector< >),表示网格图,若map[i][j]为1则说明该点不是障碍点,否则则为障碍。另外给定int x,int y,表示网格的大小。请返回机器人从(0,0)走到(x - 1,y - 1)的走法数,为了防止溢出,请将结果Mod1000000007。保证x和y均小于等于50

解析:

class Robot {
public:
	int countWays(vector<vector<int> > map, int x, int y) {
		// write code here
		vector<vector<int> > dp(x, vector<int>(y, 0));
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y; j++) {
				if (map[i][j] != 1) continue;
				if (i == 0 && j == 0) dp[0][0] = 1;
				else if (i != 0 && j == 0) dp[i][0] = dp[i - 1][0];
				else if (i == 0 && j != 0) dp[0][j] = dp[0][j - 1];
				else {
					dp[i][j] = (dp[i][j - 1] + dp[i - 1][j]) % 1000000007;
				}
			}
		}
		return dp[x - 1][y - 1];
	}
};

第七题:魔术索引I

题目:

在数组A[0…n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个升序数组,元素值各不相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。

给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。

测试样例:

[1,2,3,4,5]
返回:false

解析:

要优于O(n),使用二分
注意:二分的边界条件

class MagicIndex {
public:
	bool findMagicIndex(vector<int> A, int n) {
		// write code here
		int low = 0, high = A.size() - 1;
		while (low <= high) {
			int mid = (low + high) / 2;
			if (A[mid] == mid) {
				return true;
			}
			else if (A[mid] > mid) {
				high = mid - 1;
			}
			else if (A[mid] < mid) {
				low = mid + 1;
			}
		}
		return false;
	}
};

第八题:魔术索引II

题目:

在数组A[0…n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个不下降序列,元素值可能相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。

给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。

测试样例:

[1,1,3,4,5]
返回:true

解析:

class MagicIndex {
public:
	bool findMagicIndex(vector<int> A, int n) {
		// write code here
		int i = 0;
		while (i < n) {
			if (A[i] == i) {
				return true;
			}
			else if (A[i] > i) {
				i = A[i];
			}
			else
			{
				++i;
			}
		}
		return false;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值