11.力扣2018年常见编程题总结(数学&位运算)

1.给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]

输出: 1

解:通过采用两两异或,可以把相同的数字变为0,留下单独存在的那个数字

代码:

class Solution {
public:
	int singleNumber(vector<int>& nums) {
		int result = 0;
		for (int i = 0; i < nums.size(); i++)
			result ^= nums[i];
		return result;
	}
};


int main()
{
	Solution s1;
	vector < int> ss = { 4,1,2,1,2 };
	vector<int> s;
	cout<<s1.singleNumber(ss);
	return 0;
}

2.给定一个二维平面,平面上有 个点,求最多有多少个点在同一条直线上。

示例 1:

输入: [[1,1],[2,2],[3,3]]

输出: 3

解释:

^
|
|        o
|     o
|  o  
+------------->
0  1  2  3  4

代码:

class Solution {
public:
	int maxPoints(vector<vector<int>>& points) {
		int res = 0;
		for (int i = 0; i < points.size(); ++i) {
			map<pair<int, int>, int> m;
			int duplicate = 1;
			for (int j = i + 1; j < points.size(); ++j) {
				if (points[i][0] == points[j][0] && points[i][1] == points[j][1]) {
					++duplicate; continue;
				}
				int dx = points[j][0] - points[i][0];
				int dy = points[j][1] - points[i][1];
				int d = gcd(dx, dy);
				++m[{dx / d, dy / d}];
			}
			res = max(res, duplicate);
			for (auto it = m.begin(); it != m.end(); ++it) {
				res = max(res, it->second + duplicate);
			}
		}
		return res;
	}
	int gcd(int a, int b) {
		return (b == 0) ? a : gcd(b, a % b);
	}
};


int main()
{
	Solution s1;
	vector < vector<int>> ss = { {1,1},{2,2},{3,3} };
	vector<int> s;
	cout<<s1.maxPoints(ss);
	return 0;
}

3.给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。

如果小数部分为循环小数,则将循环的部分括在括号内。

示例 1:

输入: numerator = 1, denominator = 2

输出: "0.5"

示例 2:

输入: numerator = 2, denominator = 3

输出: "0.(6)"

解:先确定整数部分,并确定除下来后的正负号,若取模为0则表示刚好整除,否则包含小数部分,进一步确定小数,循环小数的特征是取模后的值始终相等,因此可以使用map来确定前后两次是否相等。

代码:

class Solution {
public:
	string fractionToDecimal(int numerator, int denominator) {
		int s1 = numerator >= 0 ? 1 : -1;		//分子
		int s2 = denominator >= 0 ? 1 : -1;//分母

		long long num = abs((long long)numerator);
		long long den = abs((long long)denominator);
		long long out = num / den;
		long long rem = num % den;
		unordered_map<long long, int> m;
		string res = to_string(out);//整数部分转为字符串

		//算符号
		if (s1*s2 == -1 && (out > 0 || rem > 0))
			res = "-" + res;//判断正负

		if (rem == 0)
			return res;//刚好为整数

		res += ".";
		string s = "";

		int pos = 0;
		while (rem != 0)//含有小数部分
		{
			if (m.find(rem) != m.end())
			{
				s.insert(m[rem], "(");
				s += ")";
				return res + s;
			}
			m[rem] = pos;
			s += to_string((rem * 10) / den);
			rem = (rem * 10) % den;//进一步确定小数位
			++pos;
		}
		return res + s;
	}
};


int main()
{
	Solution s1;
	vector < vector<int>> ss = { {1,1},{2,2},{3,3} };
	vector<int> s;
	cout<<s1.fractionToDecimal(33,100);
	return 0;
}

4.给定一个整数 n,返回 n! 结果尾数中零的数量。

输入: 5

输出: 1

解释: 5! = 120, 尾数中有 1 个零.

解:对于阶乘,确定0的个数即计算n中包含多少个5.

代码:

class Solution {
public:
	int trailingZeroes(int n) {
		int res = 0;
		for (int i = 1;; i++) {
			int number = n / pow(5, i);//确定有多少个能被5的幂次方整除,计算n中有多少个5
			if (number == 0)
				break;
			res += number;
		}
		return res;
	}
};
int main()
{
	Solution s1;
	cout<<s1.trailingZeroes(5);
	return 0;
}

5.颠倒给定的 32 位无符号整数的二进制位。

示例 1:

输入: 00000010100101000001111010011100

输出: 00111001011110000010100101000000

解释: 输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596 因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000

示例 2:

输入:11111111111111111111111111111101

输出:10111111111111111111111111111111

解释:输入的二进制串 11111111111111111111111111111101 表示无符号整数 4294967293,   因此返回 3221225471 其二进制表示形式为 10101111110010110010011101101001。

代码:

class Solution {
public:
	uint32_t reverseBits(uint32_t n) {
		uint32_t res = 0;
		for (int i = 0; i < 32; i++)
		{
			res = res << 1;
			res = res + (n & 1);
			n = n >> 1;
		}
		return res;
	}
};
int main()
{
	Solution s1;
	cout<<s1.reverseBits(43261596);
	return 0;
}

6.编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

解:要求二进制中1的个数,则应该从最后一位依次向左判断有多少个1,即每判断完一位,则应该减去1,判断前面的位数1,判断过的位应该全部为0.

代码:

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int count=0;
        while(n)
        {
            ++count;
            n=n&(n-1);
        }
        return count;
    }
};
int main()
{
	Solution s1;
	cout<<s1.hammingWeight(21);
	return 0;
}

7.统计所有小于非负整数 的质数的数量。

示例:

输入: 10

输出: 4

解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

代码:

class Solution {
public:
	int countPrimes(int n) {
		vector<int> p(n + 1, 1);
		int res = 0;
		if (n < 2) return 0;
		for (int i = 2; i < n; i++) 
		{
			if (p[i] == 1) {
				res += 1;
				int j = i + i;
				while (j < n) {
					p[j] = 0;
					j += i;
				}
			}
		}
		return res;
	}
};
int main()
{
	Solution s1;
	cout<<s1.countPrimes(45);
	return 0;
}

8.给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。

示例 1:

输入: [3,0,1]

输出: 2

解:运用位运算来完成,思路为temp ^ nums[ i ] ^ (i + 1),这里的temp值从0开始,因为nums 的值是从0开始,而(i + 1)则是为了取到自然数1,2,3,4,5...等。

运算规则如下:

假如目标数组nums 值 为 0,1,2,4

自然数对应为1, 2,3,4

0 ^ 1 ^ 0 = 1

1 ^ 2 ^ 1 = 2

2 ^ 3 ^ 2 = 3

3 ^ 4 ^ 4 = 3
代码:

class Solution {
public:
	int missingNumber(vector<int>& nums) {
		int temp = 0;
		for (int i = 0; i < nums.size(); i++)
		{
			temp = temp ^ (i + 1) ^ nums[i];
		}
		return temp;
	}
};
int main()
{
	Solution s1;
	vector<int> ss = { 2,4,0,1 };
	cout<<s1.missingNumber(ss);
	return 0;
}

9.给定一个整数,写一个函数来判断它是否是 3 的幂次方。

示例 1:

输入: 27

输出: true

解:判断是否为3的幂次方,可以通过while循环不断整除,若余数为1则代表是幂次方。

代码:

class Solution {
public:
	bool isPowerOfThree(int n) {
		if (n == 0) return false;
		while (n % 3 == 0) n /= 3;
		if (n == 1) return true;
		return false;
	}
};
int main()
{
	Solution s1;
	cout<<s1.isPowerOfThree(99);
	return 0;
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值