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

第一题:维护x的秩

题目:

现在我们要读入一串数,同时要求在读入每个数的时候算出它的秩,即在当前数组中小于等于它的数的个数(不包括它自身),请设计一个高效的数据结构和算法来实现这个功能。

给定一个int数组A,同时给定它的大小n,请返回一个int数组,元素为每次加入的数的秩。保证数组大小小于等于5000。

测试样例:

[1,2,3,4,5,6,7],7

返回:

[0,1,2,3,4,5,6]

解析:

比较low,遍历所有

class Rank {
public:
	vector<int> getRankOfNumber(vector<int> A, int n) {
		// write code here
		vector<int> res(n);
		res[0] = 0;
		for (int i = 1; i < n; ++i) {
			res[i] = 0;
			for (int j = 0; j < i; ++j) {
				if (A[i] >= A[j])
					++res[i];
			}
		}
		return res;
	}
};

第二题:数组中的逆序对

题目:

有一组数,对于其中任意两个数组,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一个高效的算法,计算给定数组中的逆序对个数。

给定一个int数组A和它的大小n,请返回A中的逆序对个数。保证n小于等于5000。

测试样例:

[1,2,3,4,5,6,7,0],8

返回:

7

解析:

逆序对问题,详解

class AntiOrder {
public:
	int count(vector<int> A, int n) {
		// write code here
		int res = 0;
		for (int i = 1; i < n; ++i) {
			for (int j = 0; j < i; ++j) {
				if (A[i] < A[j]) ++res;
			}
		}
		return res;
	}
};

第三题:无缓存交换

题目:

请编写一个函数,函数内不使用任何临时变量,直接交换两个数的值。

给定一个int数组AB,其第零个元素和第一个元素为待交换的值,请返回交换后的数组。

测试样例:

[1,2]

返回:

[2,1]

解析:

解析一:记住,一时间是想不到的

class Exchange {
public:
    vector<int> exchangeAB(vector<int> AB) {
        // write code here
        AB[0] = AB[0]^AB[1];
        AB[1] = AB[0]^AB[1];
        AB[0] = AB[0]^AB[1];
        return AB;
    }
};

解析二: 用加法来解决不用临时变量就能交换的问题。

例如:

a = 1; b = 2;

a = a + b = 3;

b = a(3) - b (2)= a (1)+ b (2)- b(2) = 1;

a = a(3) - b(1) = a(1) + b(2) - ( a(1) + b(2) - b(2) ) = 2;

括号里的数字代表的数当前字母的值

class Exchange {
public:
    vector<int> exchangeAB(vector<int> AB) {
        // write code here
        AB[1] = AB[0] + AB[1];
        AB[0] = AB[1] - AB[0];  //AB[1]
        AB[1] = AB[1] - AB[0];
        return AB;
    }
};

第四题:井字棋

题目:

对于一个给定的井字棋棋盘,请设计一个高效算法判断当前玩家是否获胜。

给定一个二维数组board,代表当前棋盘,其中元素为1的代表是当前玩家的棋子,为0表示没有棋子,为-1代表是对方玩家的棋子。

测试样例:

[[1,0,1],[1,-1,-1],[1,-1,0]]

返回:

true

解析:

解析一:检测所有获胜的条件

class Board {
public:
	bool checkWon(vector<vector<int> > board) {
		// write code here
		if (board[0][0] == 1) {
			if (board[0][1] == 1 && board[0][2] == 1) return true;
			if (board[1][0] == 1 && board[2][0] == 1) return true;
		}
		if (board[2][2] == 1) {
			if (board[2][0] == 1 && board[2][1] == 1) return true;
			if (board[0][2] == 1 && board[1][2] == 1) return true;
		}
		if (board[1][1] == 1) {
			if (board[1][0] == 1 && board[1][2] == 1) return true;
			if (board[0][1] == 1 && board[2][1] == 1) return true;
			if (board[0][0] == 1 && board[2][2] == 1) return true;
			if (board[0][2] == 1 && board[2][0] == 1) return true;
		}
		return false;
	}
};

解析二:3竖3横两条斜线

class Board {
public:
	bool checkWon(vector<vector<int> > board) {
		// write code here
		if (board[0][0] + board[1][1] + board[2][2] == 3) return true;
		if (board[0][2] + board[1][1] + board[2][0] == 3) return true;
		for (int i = 0; i < 3; i++) {
			if (board[i][0] + board[i][1] + board[i][2] == 3) return true;
			if (board[0][i] + board[1][i] + board[2][i] == 3) return true;
		}
		return false;
	}
};

第五题:无判断max

题目:

请编写一个方法,找出两个数字中最大的那个。条件是不得使用if-else等比较和判断运算符。

给定两个int a和b,请返回较大的一个数。若两数相同则返回任意一个。

测试样例:

1,2

返回:

2

解析:

a和b的差的绝对值是abs(a - b),然后差的绝对值加上a和b的和即为最大值的两倍。
同理求两数较小的一个,a + b - abs(a - b)即可。

class Max {
public:
	int getMax(int a, int b) {
		// write code here
		return (a + b + abs(a - b)) / 2;
	}
};

第六题:珠玑妙算

题目:

我们现在有四个槽,每个槽放一个球,颜色可能是红色®、黄色(Y)、绿色(G)或蓝色(B)。例如,可能的情况为RGGB(槽1为红色,槽2、3为绿色,槽4为蓝色),作为玩家,你需要试图猜出颜色的组合。比如,你可能猜YRGB。要是你猜对了某个槽的颜色,则算一次“猜中”。要是只是猜对了颜色但槽位猜错了,则算一次“伪猜中”。注意,“猜中”不能算入“伪猜中”。

给定两个string A和guess。分别表示颜色组合,和一个猜测。请返回一个int数组,第一个元素为猜中的次数,第二个元素为伪猜中的次数。

测试样例:

“RGBY”,“GGRR”

返回:

[1,1]

解析:

class Result {
public:
	vector<int> calcResult(string A, string guess) {
		// write code here
		vector<int> res(2, 0);
		int count = 0;
		int r1 = 0, y1 = 0, g1 = 0, b1 = 0;
		int r2 = 0, y2 = 0, g2 = 0, b2 = 0;
		for (int i = 0; i < A.size(); ++i) {
			if (A[i] == guess[i]) ++count;
			if (A[i] == 'R') {
				++r1;
			}
			else if (A[i] == 'Y') {
				++y1;
			}
			else if (A[i] == 'G') {
				++g1;
			}
			else if (A[i] == 'B') {
				++b1;
			}

			if (guess[i] == 'R') {
				++r2;
			}
			else if (guess[i] == 'Y') {
				++y2;
			}
			else if (guess[i] == 'G') {
				++g2;
			}
			else if (guess[i] == 'B') {
				++b2;
			}
		}
		int sum = 0;
		sum += r1 < r2 ? r1 : r2;
		sum += y1 < y2 ? y1 : y2;
		sum += g1 < g2 ? g1 : g2;
		sum += b1 < b2 ? b1 : b2;
		res[0] = count;
		res[1] = sum - count;
		return res;
	}
};

第七题:阶乘尾零

题目:

请设计一个算法,计算n的阶乘有多少个尾随零。

给定一个int n,请返回n的阶乘的尾零个数。保证n为正整数。

测试样例:

5

返回:

1

解析:

计算阶乘中因子为5的个数

class Factor {
public:
	int getFactorSuffixZero(int n) {
		// write code here
		int sum = 0;
		while (n) {
			n /= 5;
			sum += n;
		}
		return sum;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值