本系列笔记供自学算法用,仅记载题解代码和部分题解思路,所有题目版权归LeeCode及《剑指offer》所有;推荐一超棒的刷题笔记系列博客,本系列的题型分类均有所参考:剑指Offer系列刷题笔记汇总
注:题目序号以现官网中排序为准,或和其他参考有所出入;
文章目录
15.二进制中1的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
输入:n = 11 (控制台输入 00000000000000000000000000001011)
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。
解答:
class Solution {
public:
int hammingWeight(uint32_t n) {
int ans = 0;
while (n != 0)
{
++ans;
n &= (n - 1);//消除n的最低位1
//n = (n - 1) & n;
}
return ans;
}
};
16.数值的整数次方
实现 pow(x, n),即计算 x 的 n 次幂函数(即x^n)。不得使用库函数,同时不需要考虑大数问题。
输入:x = 2.00000, n = 10
输出:1024.00000提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104
解答:
class Solution {
public:
double myPow(double x, int n) {
if (x == 1 || n == 0) return 1; // 特殊情况
double ret = 1; // 运算结果
long exp = long(n);
// 若指数为负数,就转换成多个底数的倒数进行运算
if (n < 0) {
x = 1/ x;
exp = -exp;
}
// 进行快速幂
while (exp) {
if (exp & 1) ret *= x; //编译后所有数据都是二进制表示故可运用右移
x *= x;//每次代表x的1,2,4,8次方
exp >>= 1;
}
return ret;
}
};
//作者:RyanWangllng
//链接:https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/solution/zhu-shi-xing-ti-jie-kuai-su-mi-jian-zhi-rc5mo/
class Solution { //另一种迭代解法
public:
double myPow(double x, int n) {
if(n==0) return 1;
if(n==-1) return 1/x;
if(n&1) return myPow(x*x,n>>1)*x;
else return myPow(x*x,n>>1);
}
};
//来源用户:https://leetcode-cn.com/u/luo-an/
29.顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]限制:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100
解答:
class Solution { //模拟打印路径
private:
static constexpr int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return {};
}
int rows = matrix.size(), columns = matrix[0].size();
vector<vector<bool>> visited(rows, vector<bool>(columns));
int total = rows * columns;
vector<int> order(total);
int row = 0, column = 0;
int directionIndex = 0;
for (int i = 0; i < total; i++) {
order[i] = matrix[row][column];
visited[row][column] = true;
int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];
if (nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn]) {
directionIndex = (directionIndex + 1) % 4;
}
row += directions[directionIndex][0];
column += directions[directionIndex][1];
}
return order;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/solution/shun-shi-zhen-da-yin-ju-zhen-by-leetcode-solution/
class Solution { //按层模拟
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return {};
}
int rows = matrix.size(), columns = matrix[0].size();
vector<int> order;
int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
while (left <= right && top <= bottom) {
for (int column = left; column <= right; column++) {
order.push_back(matrix[top][column]);
}
for (int row = top + 1; row <= bottom; row++) {
order.push_back(matrix[row][right]);
}
if (left < right && top < bottom) {
for (int column = right - 1; column > left; column--) {
order.push_back(matrix[bottom][column]);
}
for (int row = bottom; row > top; row--) {
order.push_back(matrix[row][left]);
}
}
left++;
right--;
top++;
bottom--;
}
return order;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/solution/shun-shi-zhen-da-yin-ju-zhen-by-leetcode-solution/
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> v;
int rows = matrix.size();
if(rows==0) return v;
int cols = matrix[0].size();
if(cols==0) return v;
int up = 0,down = rows-1,left = 0,right = cols-1;
int i,j;
while(up<=down && left<=right){
i=up,j=left;
//往右
while(j<=right)
v.push_back(matrix[i][j++]);
up++;j--;i++;
if(up>down) break;
//往下
while(i<=down)
v.push_back(matrix[i++][j]);
right--;i--;j--;
if(left>right) break;
//往左
while(j>=left)
v.push_back(matrix[i][j--]);
down--;j++;i--;
if(up>down) break;
//往上
while(i>=up)
v.push_back(matrix[i--][j]);
left++;
if(left>right) break;
}
return v;
}
};
//来自:https://leetcode-cn.com/u/joanne-2/
40.最小的k个数
输入整数数组 arr
,找出其中最小的 k
个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
解答:
class Solution { //对原数组从小到大排序后取出前 kk 个数即可。
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
vector<int> vec(k, 0);
sort(arr.begin(), arr.end());
for (int i = 0; i < k; ++i) {
vec[i] = arr[i];
}
return vec;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/zui-xiao-de-kge-shu-by-leetcode-solution/
class Solution { //使用堆
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
vector<int> vec(k, 0);
if (k == 0) { // 排除 0 的情况
return vec;
}
priority_queue<int> Q;
for (int i = 0; i < k; ++i) {
Q.push(arr[i]);
}
for (int i = k; i < (int)arr.size(); ++i) {
if (Q.top() > arr[i]) {
Q.pop();
Q.push(arr[i]);
}
}
for (int i = 0; i < k; ++i) {
vec[i] = Q.top();
Q.pop();
}
return vec;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/zui-xiao-de-kge-shu-by-leetcode-solution/
41.数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
输入:
[“MedianFinder”,“addNum”,“addNum”,“findMedian”,“addNum”,“findMedian”]
[[],[1],[2],[],[3],[]]
输出:[null,null,null,1.50000,null,2.00000]
解答:
class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder() {
}
priority_queue<int> max_heap;
priority_queue<int, vector<int>, greater<int>> min_heap;
void addNum(int num) {
max_heap.push(num);//先把元素放入大根堆
if(min_heap.size() && max_heap.top() > min_heap.top())//再判断转移到小根堆还是大根堆
{
auto min1 = min_heap.top(), max1 = max_heap.top();
max_heap.pop(), min_heap.pop();
max_heap.push(min1);
min_heap.push(max1);
}
if(max_heap.size() > min_heap.size() + 1)//再转移到小根堆
{
auto t = max_heap.top();
max_heap.pop();
min_heap.push(t);
}
}
double findMedian() {
if(max_heap.size() + min_heap.size() & 1) return max_heap.top();
return (max_heap.top() + min_heap.top()) / 2.0 ;//大根堆和小根堆的顶点即是我们要的两点
}
};
//作者:feng-sheng-he-li
//链接:https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/solution/jian-zhi-offerdi-41ti-ti-jie-dui-de-ying-vnw5/
class MedianFinder { //大根堆小根堆
public:
/** initialize your data structure here. */
MedianFinder() {
}
void addNum(int num) {
//当数据流总量为偶数的时候,插入右侧小根堆
if(((max.size()+min.size()) & 1) == 0)
{
//如果插入的数字比左侧大根堆中最大的数字要小,则不能直接插入右侧小根堆,需要调整
if((!max.empty())&&num < max.front())
{
max.push_back(num);
//最后一个参数为function object
push_heap(max.begin(),max.end(),less<int>());
//把左侧右根堆中最大的数字拿出来,准备插入右侧小根堆
num = max.front();
pop_heap(max.begin(),max.end(),less<int>());
max.pop_back();
}
//如果原来的num比左侧大根堆中最大的数字小,插入的就是左侧大根堆中最大的数字,否则就将原来的num直接插入右侧小根堆中
min.push_back(num);
push_heap(min.begin(),min.end(),greater<int>());
}
//当数据流总量为奇数的时候,插入左侧大根堆
else
{
//如果num比右侧小根堆中最小的数字大,则不能直接插入左侧大根堆,需要调整
if((!min.empty())&&num > min.front())
{
min.push_back(num);
push_heap(min.begin(),min.end(),greater<int>());
num = min.front();
pop_heap(min.begin(),min.end(),greater<int>());
min.pop_back();
}
//如果原来的num比右侧小根堆中最小的数字大,插入的就是右侧小根堆中最小的数字,否则就将原来的num直接插入左侧大根堆中
max.push_back(num);
push_heap(max.begin(),max.end(),less<int>());
}
}
double findMedian() {
int length = min.size() + max.size();
if(length == 0)
return -1;
//长度为奇数,返回小根堆中最小的数字
if(length & 1)
return min.front();
//长度为偶数,返回小根堆中最小的数字与大根堆中最大的数字的平均
else
return (double)(min.front() + max.front()) / 2;
}
private:
//利用两个vector容器实现堆,利用大根堆和小根堆实现查找数据流中的中位数
vector<int> max;
vector<int> min;
};
//作者:emergence
//链接:https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/solution/jian-zhi-offer-41shu-ju-liu-zhong-de-zho-io05/
43.整数中1出现的次数
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
输入:n = 12
输出:5限制:
1 <= n < 2^31
解答:
class Solution {
public:
int countDigitOne(int n) {
if(n == 0) return 0;
if(n < 10) return 1;
long long cur = 1;
int i = 0, res = 0;
while(cur < n) {cur *= 10; ++i;} // 找出 n 的位数
cur /= 10;
if(cur*10 == n) return i*cur+1; // n == 10^i, 直接返回
--i;
while(cur > 0) {
int t = n / cur;
n = n % cur;
if(t == 1) res += i*cur/10 + n + 1;
else res += t * i*cur/10 + cur;
while(cur > n) {cur /= 10; --i;} // 将 i 更新为 n 的位数
}
return res;
}
};
//作者:yarecandy
//链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/shi-jin-zhi-shu-zhong-1de-ge-shu-c-100-b-kcsv/
class Solution {
public:
int countDigitOne(int n) {
// 个数的累加和
int res = 0;
int H = n / 10;
int L = 0;
long base = 1;
int Xi = n % 10;
// 如果两个都为0,表示已经都遍历完了
while (H != 0 || Xi != 0)
{
// 直接把三部分合成在一起计算了
res += H*base + ((Xi > 1) ? base : 0) + ((Xi == 1) ? (1+L) : 0);
// cout << Xi << " "<< res << endl;
// 注意这里顺序,避免被错误修改
L += Xi*base;
Xi = H % 10;
H /= 10;
base *= 10;
}
return res;
}
};
//作者:ffreturn
//链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/cchao-100de-shu-xue-jie-fa-by-ffreturn-ije9/
49.丑数
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。说明:
1 是丑数。
n 不超过1690。
class Solution { //最小堆
public:
int nthUglyNumber(int n) {
vector<int> factors = {2, 3, 5};
unordered_set<long> seen;
priority_queue<long, vector<long>, greater<long>> heap;
seen.insert(1L);
heap.push(1L);
int ugly = 0;
for (int i = 0; i < n; i++) {
long curr = heap.top();
heap.pop();
ugly = (int)curr;
for (int factor : factors) {
long next = curr * factor;
if (!seen.count(next)) {
seen.insert(next);
heap.push(next);
}
}
}
return ugly;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/chou-shu-lcof/solution/chou-shu-by-leetcode-solution-0e5i/
class Solution {
public:
int nthUglyNumber(int n) {
priority_queue<long,vector<long>,greater<long>>aque;
aque.push(1);
set<long>st;
st.insert(1);
long x;
vector<long>temp={2,3,5};
for(int i=0;i<n;i++){
x=aque.top();
aque.pop();
for(int k=0;k<3;k++){
if(st.find(temp[k]*x)==st.end()){
aque.push(temp[k]*x);
st.insert(temp[k]*x);
}
}
}
return x;
}
};
//作者:LWLVHY
//链接:https://leetcode-cn.com/problems/chou-shu-lcof/solution/shu-xue-you-xian-ji-dui-lie-by-lwlvhy-79el/
class Solution { //三路归并思想
public:
int nthUglyNumber(int n) {
vector<int> q(1, 1);
int i = 0, j = 0, k = 0;
while(--n)
{
int t = min(q[i] * 2, min(q[j] * 3, q[k] * 5));
q.push_back(t);
if(t == q[i] * 2) i++;
if(t == q[j] * 3) j++;
if(t == q[k] * 5) k++;
}
return q.back();
}
};
//作者:feng-sheng-he-li
//链接:https://leetcode-cn.com/problems/chou-shu-lcof/solution/jian-zhi-offerdi-49ti-ti-jie-san-lu-gui-t37cd/
50.字符流中第一个不重复的字符
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
s = “abaccdeff”
返回 “b”
s = “”
返回 " "限制:
0 <= s 的长度 <= 50000
解答:
class Solution {
public:
char firstUniqChar(string s) {
unordered_map<int, int> frequency;
for (char ch: s) {
++frequency[ch];
}
for (int i = 0; i < s.size(); ++i) {
if (frequency[s[i]] == 1) {
return s[i];
}
}
return ' ';
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/solution/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-by-3zqv5/
class Solution { //另一种简便写法
public:
char firstUniqChar(string s) {
unordered_map<char, bool> dic;
for(char c : s)
dic[c] = dic.find(c) == dic.end();
for(char c : s)
if(dic[c]) return c;
return ' ';
}
};
//作者:jyd
//链接:https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/solution/mian-shi-ti-50-di-yi-ge-zhi-chu-xian-yi-ci-de-zi-3/
class Solution { //有序哈希表
public:
char firstUniqChar(string s) {
vector<char> keys;
unordered_map<char, bool> dic;
for(char c : s) {
if(dic.find(c) == dic.end())
keys.push_back(c);
dic[c] = dic.find(c) == dic.end();
}
for(char c : keys) {
if(dic[c]) return c;
}
return ' ';
}
};
//作者:jyd
//链接:https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/solution/mian-shi-ti-50-di-yi-ge-zhi-chu-xian-yi-ci-de-zi-3/
57.和为S的两个数字
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]限制:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^6
解答:
class Solution { //哈希集合
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_set<int> s;
for (int i : nums)
{
if (s.find(target - i) == s.end())
{
s.insert(i);
}
else
{
return vector<int>{target - i, i};
}
}
return vector<int>();
}
};
作者:LonelyTaoist
链接:https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof/solution/he-wei-sde-liang-ge-shu-zi-ji-he-orshuan-nnc6/
class Solution { //双指针
public:
vector<int> twoSum(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left < right)
{
if (nums[left] + nums[right] == target)
{
return vector<int>{nums[left], nums[right]};
}
else if (nums[left] + nums[right] < target)
{
++left;
}
else
{
--right;
}
}
return vector<int>();
}
};
//作者:LonelyTaoist
//链接:https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof/solution/he-wei-sde-liang-ge-shu-zi-ji-he-orshuan-nnc6/
57-2.和为S的连续正数序列
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
输入:target = 9
输出:[[2,3,4],[4,5]]限制:
1 <= target <= 10^5
解答:
class Solution { //枚举/暴力解法
public:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> vec;
vector<int> res;
int sum = 0, limit = (target - 1) / 2; // (target - 1) / 2 等效于 target / 2 下取整
for (int i = 1; i <= limit; ++i) {
for (int j = i;; ++j) {
sum += j;
if (sum > target) {
sum = 0;
break;
} else if (sum == target) {
res.clear();
for (int k = i; k <= j; ++k) {
res.emplace_back(k);
}
vec.emplace_back(res);
sum = 0;
break;
}
}
}
return vec;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/solution/mian-shi-ti-57-ii-he-wei-sde-lian-xu-zheng-shu-x-2/
vector<vector<int>> findContinuousSequence(int target) { //滑动窗口
int i = 1; // 滑动窗口的左边界
int j = 1; // 滑动窗口的右边界
int sum = 0; // 滑动窗口中数字的和
vector<vector<int>> res;
while (i <= target / 2) {
if (sum < target) {
// 右边界向右移动
sum += j;
j++;
} else if (sum > target) {
// 左边界向右移动
sum -= i;
i++;
} else {
// 记录结果
vector<int> arr;
for (int k = i; k < j; k++) {
arr.push_back(k);
}
res.push_back(arr);
// 左边界向右移动
sum -= i;
i++;
}
}
return res;
}
//作者:nettee
//链接:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/solution/shi-yao-shi-hua-dong-chuang-kou-yi-ji-ru-he-yong-h/
61.扑克牌顺子
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
输入: [1,2,3,4,5]
输出: True限制:
数组长度为 5
数组的数取值为 [0, 13] .
解答:
class Solution { //暴力解法
public:
bool isStraight(vector<int>& nums) {
sort(nums.begin(), nums.end());
int king = 0;
for (int i = 0; i < nums.size() -1; i ++) {
// 统计大小王个数
if (nums[i] == 0) {
king ++;
continue;
}
// 若当前数字与之后数字相等(不符合顺子要求)返回false
if (nums[i] == nums[i + 1])
return false;
// 若当前数字与之后数字是否只相差 1(符合顺子要求)直接判断下一张牌
if (nums[i + 1] == nums[i] + 1)
continue;
// 若当前数字与之后数字相差大于 1,则不够的中间牌可以用大小王去替,
// 若大小王的数量不够则返回false,够则检查下一张排
if (nums[i + 1] > nums[i] + 1) {
king -= nums[i + 1] - nums[i] - 1;
if (king < 0 )
return false;
}
}
return true;
}
};
//作者:master_xue
//链接:https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/solution/huan-huan-xiang-kou-yi-ti-duo-jie-by-mas-4a4p/
class Solution { //效率更高的解法
public:
bool isStraight(vector<int>& nums) {
sort(nums.begin(),nums.end());
int count_0 = 0;
int i;
for (i = 0; i < nums.size(); i++) // 统计0的个数
{
if (nums[i] == 0)
count_0++;
else
break;
}
while(i+1 < nums.size()) // 接着遍历0后面的数
{
if(nums[i+1] == nums[i]+1) // 如果是顺子就遍历下一张
i++;
else
{
if(--count_0 < 0) return false; // count当作万能牌,用一张少一张,当没有万能牌时就不是顺子。
nums[i] += 1; // 用完一张的效果:将当前的数加一
}
}
return true;
}
};
//作者:bill-jiao
//链接:https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/solution/ji-hu-shuang-bai-by-bill-jiao-dp9f/
62.圆圈中最后剩下的数
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
输入: n = 5, m = 3
输出: 3限制:
1 <= n <= 10^5
1 <= m <= 10^6
解答:
class Solution { //数学+递归
int f(int n, int m) {
if (n == 1) {
return 0;
}
int x = f(n - 1, m);
return (m + x) % n;
}
public:
int lastRemaining(int n, int m) {
return f(n, m);
}
};
class Solution { //数学+迭代
public:
int lastRemaining(int n, int m) {
int f = 0;
for (int i = 2; i != n + 1; ++i) {
f = (m + f) % i;
}
return f;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-by-lee/
64.求1+2+3+…+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
输入: n = 3
输出: 6
示例 2:限制:
1 <= n <= 10000
解答:
class Solution { //递归
public:
int sumNums(int n) {
return n == 0 ? 0 : n + sumNums(n - 1);
}
};
class Solution { //未用判断的递归
public:
int sumNums(int n) {
n && (n += sumNums(n-1));
return n;
}
};
int quickMulti(int A, int B) { //快速乘
int ans = 0;
for ( ; B; B >>= 1) {
if (B & 1) {
ans += A;
}
A <<= 1;
}
return ans;
}
class Solution { //总解法
public:
int sumNums(int n) {
int ans = 0, A = n, B = n + 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
return ans >> 1;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/qiu-12n-lcof/solution/qiu-12n-by-leetcode-solution/
65.不用加减乘除的加法
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
输入: a = 1, b = 1
输出: 2提示:
a, b 均可能是负数或 0
结果不会溢出 32 位整数
解答:
class Solution { //位运算
public:
int add(int a, int b) {
while (b) {
// 无进位求和
int not_carry = a ^ b;
// 求进位数(这里负数会报错,转成无符号)
// 求出的进位数要左移一位,
// 例如:进位数是1,左移一位才是10
int carry = ((unsigned int)(a & b) << 1);
// 一直循环,直到不需要进位为止
a = not_carry;
b = carry;
}
return a;
}
};
//作者:RyanWangllng
//链接:https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/solution/zhu-shi-xing-ti-jie-wei-yun-suan-jian-zh-1neg/
class Solution { //另一种递归解法
public:
int add(int a, int b) {
// 后续用a表示非进位和,b表示进位,当进位为0,则表示计算结束
//位运算的实现
//总结规律如下(可自行推导)
//(a&b)<<1 进位
//a^b 是非进位和 (不包含进位的结果)
return b == 0 ? a : add(a^b, (unsigned int)(a&b) << 1);
}
};
//作者:ffreturn
//链接:https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/solution/cchao-100de-yi-xing-dai-ma-by-ffreturn-j3df/