给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 ‘*’、除号 ‘/’ 以及求余符号 ‘%’ 。
注意:
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1
解题关键
class Solution {
public:
int divide(int a, int b) {
if (a == INT_MIN && b == -1) {
return INT_MAX;
}
int negative = 2;
if (a > 0) {
negative--;
a = -a;
}
if (b > 0) {
negative--;
b = -b;
}
//全部转成了负数,因为INT的范围是 -2^31 ~ 2^31 -1 变负数可防止溢出
unsigned int ret = divideCore(a, b);
return negative == 1 ? -ret : ret;
}
unsigned int divideCore(int a, int b) {
int ret = 0;
// 注意a, b都是负数,所以a <= b就是还可以继续除
while (a <= b) {
int value = b;
unsigned int quo = 1;
while (value >= 0xc0000000 && a <= value + value) { //0xc0000000是-2^30
value += value;
}
ret += quo;
a -= value;
}
return ret;
}
};
给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。
输入为 非空 字符串且只包含数字 1 和 0。
示例 1:
输入: a = “11”, b = “10”
输出: “101”
示例 2:
输入: a = “1010”, b = “1011”
输出: “10101”
提示:每个字符串仅由字符 ‘0’ 或 ‘1’ 组成。 1 <= a.length, b.length <= 10^4。 字符串如果不是 “0” ,就都不含前导零。
解题关键
class Solution {
public:
string addBinary(string a, string b) {
string res;
int lenA = a.size();
int lenB = b.size();
int maxSize = max(lenA, lenB);
res.resize(maxSize);
if(lenA > lenB){
string tmp(lenA - lenB, '0');
b = tmp + b;
}else if(lenA < lenB){
string tmp(lenB - lenA, '0');
a = tmp + a; //补充前导位
}
int up = '0';
for(int i=a.size() - 1; i >= 0; i--){
if(a[i]=='1' && b[i]=='1'){
if(up == '0'){
res[i] = '0';
up = '1';
}else{
res[i] = '1';
}
}else if((a[i]-'0') ^ (b[i]-'0')){
if(up == '0'){
res[i] = '1';
}else{
res[i] = '0';
}
}else{
if(up == '0'){
res[i] = '0';
}else{
res[i] = '1';
}
up = '0';
}
}
return up=='0'? res : '1' + res;
}
};
给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。
示例 1:
输入: n = 2
输出: [0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10
示例 2:
输入: n = 5
输出: [0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101
说明 :
0 <= n <= 105
进阶:
给出时间复杂度为 O(n*sizeof(integer)) 的解答非常容易。但你可以在线性时间 O(n) 内用一趟扫描做到吗?
要求算法的空间复杂度为 O(n) 。
你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如 C++ 中的 __builtin_popcount )来执行此操作。
解题关键:
class Solution {
public:
vector<int> countBits(int n) {
//计算每个数二进制形式时1的个数: i&(i-1) 利用这个可每次消去一个1
vector<int> res(n+1, 0);
//动态规划
for(int i=1; i<=n; i++){
res[i] = res[i&(i-1)] + 1;
}
return res;
}
};
class Solution {
public:
vector<int> countBits(int n) {
//计算每个数二进制形式时1的个数: i&(i-1) 利用这个可每次消去一个1
vector<int> res(n+1, 0);
//动态规划
//还可以利用一下奇偶性 如果当前数是偶数的话,那么前一个数肯定是奇数
for(int i=1; i<=n; i++){
res[i] = res[i>>1] + (i&1);
}
return res;
}
};
给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
示例 1:
输入:nums = [2,2,3,2]
输出:3
示例 2:
输入:nums = [0,1,0,1,0,1,100]
输出:100
提示:
1 <= nums.length <= 3 * 104
-2^31 <= nums[i] <= 2^31 - 1
nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
进阶:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
解题关键:
class Solution {
public:
int singleNumber(vector<int>& nums) {
//线性时间复杂度
int res = 0;
int k = 3;
for(int i=0; i<32; i++){
int cnt = 0;
for(auto num : nums){
cnt += (num>>(31-i))&1; //统计每个数字的每一位是否为1, 如果为1就加到对应的结果
}
res = (res <<1) + (cnt%k!=0);
}
return res;
}
};
给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。
示例 1:
输入: words = [“abcw”,“baz”,“foo”,“bar”,“fxyz”,“abcdef”]
输出: 16
解释: 这两个单词为 “abcw”, “fxyz”。它们不包含相同字符,且长度的乘积最大。
示例 3:
输入: words = [“a”,“aa”,“aaa”,“aaaa”]
输出: 0
解释: 不存在这样的两个单词。
提示:
2 <= words.length <= 1000
1 <= words[i].length <= 1000
words[i] 仅包含小写字母
解题关键:
class Solution {
public:
int maxProduct(vector<string>& words) {
//每一个字符串都可以用一个26位的二进制数表示,a对应第0位,z对应第25位 也对应一个十进制数
vector<int> nums(words.size(), 0);
for(int i=0; i<words.size(); i++){
for(auto w : words[i]){
nums[i] |= (1<<(w-'a'));
}
}
int res = 0;
for(int j=0; j<nums.size()-1; j++){
for(int k=j+1; k<nums.size(); k++){
if( (nums[j] & nums[k]) ==0){
int tmp = words[j].length() * words[k].length();
res = res > tmp ? res : tmp;
}
}
}
return res;
}
};
给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 0 开始计数 ,所以答案数组应当满足 0 <= answer[0] < answer[1] < numbers.length 。
假设数组中存在且只存在一对符合条件的数字,同时一个数字不能使用两次。
示例 1:
输入:numbers = [1,2,4,6,10], target = 8
输出:[1,3]
解释:2 与 6 之和等于目标数 8 。因此 index1 = 1, index2 = 3 。
解题思路:
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
//排序数组用双指针 如果sum大于target右移left指针,如果小于target则左移right指针
int left = 0, right = numbers.size()-1;
vector<int> res;
while(left < right){
if(numbers[left] + numbers[right] > target){
right--;
}else if(numbers[left] + numbers[right] < target){
left++;
}else{
res.push_back(left);
res.push_back(right);
return res;
}
}
return res;
}
};