面试---(x&y) + ( (x^y)>>1 )求平均数

位运算求平均值
本文介绍了一种使用位运算求两个整数平均值的方法。通过分析位运算符&和^的特点,结合二进制位的三种可能组合,推导出位运算求平均值的通用公式,最终简化为直接计算两数之和除以二。

对于位运算求两个数的平均值问题,(整形数据)

int  average(int x,int y)
{
return ( (x&y) + ( (x^y)>>1 ) );
}

给出两个整数,求出结果。
刚开始看到这道题的做法就是x和y转换为二进制,然后计算出结果。在没有办法的情况下这样做也可以得出结果。

跟你想象的一点不差,这里确实有捷径。

题目中的&和^都是位运算,所以我们有必要研究数据的对位情况。任何数据只有3种情况。

1) 0 与 0对应
2) 0 与 1对应
3) 1 与 1对应

那么它们分别什么诀窍呢?

举例子来说:0101 和1101 也就是x和y分别为5、13.这两个数据出现了所谓的3种对应位情况。
我们可以把数据拆开来看: 5=0000+100+00+1
13=1000+100+00+1
他们分为为第一位,第二位,…..

(1)当0和1对应时,x&y结果为0, x^y的结果呢?是不是就是x和y中那个对应位不为0的数据。
例如:上面数据的第四位0和1对位。此时x^y的结果就是1000,正是1101的第四位结果。
再右移一位,相当于除以2,所以:

当 0和1对位时原函数结果为 :(x&y) + ( (x^y)>>1 ) = 0+ (x+y)/2 = (x+y)/2;

(2)看1和1对应,1^1的结果为0,所以原函数后半部分不考虑,1&1结果为1,这也是(x+y)/2;
例如:第一位和第三位的对位,都为100,他们相与的结果和相加除以2相等,即x&y=(x+y)/2;

当 1和1对位时原函数结果为 :(x&y) + ( (x^y)>>1 ) = (x+y)/2 +0 = (x+y)/2;

(3)0与0对应的时候,无论怎么样都是0,即也符合(x+y)/2.

综合上述三种情况,我们可以知道其实原函数返回就是(x+y)/2。
可改写为:
return (x+y)/2;

这是程序员面试宝典中的一道题,我认为作者在书中的解释 (x&y)为x和y相同位的一半,这该怎么理解呢?我觉得这是一个错误解释。希望大家读书能有明辨的能力。

转自http://blog.youkuaiyun.com/leo115/article/details/7993110

#include <iostream> #include <vector> #include <cmath> #include <algorithm> // 定义点的结构体 struct Point { double x; double y; }; // 计算两点之间的距离 double distance(const Point& p1, const Point& p2) { return std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); } // 计算小狗能打到小猫的所有组合 std::vector<std::vector<int>> calculateCombinations(const std::vector<Point>& dogs, const std::vector<double>& dogRanges, const std::vector<Point>& cats) { std::vector<std::vector<int>> combinations(dogs.size()); for (size_t i = 0; i < dogs.size(); ++i) { for (size_t j = 0; j < cats.size(); ++j) { if (distance(dogs[i], cats[j]) <= dogRanges[i]) { combinations[i].push_back(j); } } } return combinations; } // 生成所有可能的小狗攻击小猫的组合 void generateAllCombinations(const std::vector<std::vector<int>>& dogCombinations, int dogIndex, std::vector<int>& currentCombination, std::vector<std::vector<int>>& allCombinations) { if (dogIndex == dogCombinations.size()) { allCombinations.push_back(currentCombination); return; } if (dogCombinations[dogIndex].empty()) { currentCombination.push_back(-1); generateAllCombinations(dogCombinations, dogIndex + 1, currentCombination, allCombinations); currentCombination.pop_back(); } else { for (int catIndex : dogCombinations[dogIndex]) { currentCombination.push_back(catIndex); generateAllCombinations(dogCombinations, dogIndex + 1, currentCombination, allCombinations); currentCombination.pop_back(); } } } // 计算组合的价值 double calculateValue(const std::vector<int>& combination, const std::vector<double>& catValues) { std::vector<bool> catUsed(catValues.size(), false); double totalValue = 0; for (int catIndex : combination) { if (catIndex != -1 && !catUsed[catIndex]) { totalValue += catValues[catIndex]; catUsed[catIndex] = true; } } return totalValue; } // 找到价值最大的所有组合 std::pair<int, std::vector<std::vector<int>>> findMaxValueCombinations(const std::vector<std::vector<int>>& allCombinations, const std::vector<double>& catValues) { double maxValue = 0; std::vector<std::vector<int>> maxCombinations; for (const auto& combination : allCombinations) { double value = calculateValue(combination, catValues); if (value > maxValue) { maxValue = value; maxCombinations.clear(); maxCombinations.push_back(combination); } else if (value == maxValue) { maxCombinations.push_back(combination); } } return {maxValue, maxCombinations}; } int main() { // 初始化 20 只小狗的坐标 std::vector<Point> dogs(20); for (int i = 0; i < 20; ++i) { dogs[i] = {i * 1.0, i * 1.0}; } // 初始化 20 只小狗能跑的最远距离 std::vector<double> dogRanges(20); for (int i = 0; i < 20; ++i) { dogRanges[i] = 5.0; } // 初始化 30 只小猫的坐标 std::vector<Point> cats(30); for (int i = 0; i < 30; ++i) { cats[i] = {i * 0.5, i * 0.5}; } // 初始化 30 只小猫的价值 std::vector<double> catValues(30); for (int i = 0; i < 30; ++i) { catValues[i] = i + 1; } // 计算小狗能打到小猫的所有组合 std::vector<std::vector<int>> dogCombinations = calculateCombinations(dogs, dogRanges, cats); // 生成所有可能的小狗攻击小猫的组合 std::vector<std::vector<int>> allCombinations; std::vector<int> currentCombination; generateAllCombinations(dogCombinations, 0, currentCombination, allCombinations); // 找到价值最大的所有组合 auto [maxValue, maxCombinations] = findMaxValueCombinations(allCombinations, catValues); // 输出小狗能打到小猫的所有组合 std::cout << "小狗能打到小猫的所有组合:" << std::endl; for (const auto& combination : dogCombinations) { for (int catIndex : combination) { std::cout << catIndex << " "; } std::cout << std::endl; } // 输出最大价值 std::cout << "最大价值: " << maxValue << std::endl; // 输出价值最大的所有组合 std::cout << "价值最大的所有组合:" << std::endl; for (const auto& combination : maxCombinations) { for (int catIndex : combination) { std::cout << catIndex << " "; } std::cout << std::endl; } return 0; } 运行存在bad_alloc问题,如何优化代码
最新发布
10-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值