剑指offer(C++)——其他算法

本文是关于《剑指offer》书中部分算法题目的C++实现笔记,涵盖了二进制计数、指数运算、矩阵遍历、数组操作、数据流处理、数论问题等多个方面。通过实例代码和解析,帮助读者掌握算法思想和编程技巧。
摘要由CSDN通过智能技术生成

本系列笔记供自学算法用,仅记载题解代码和部分题解思路,所有题目版权归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/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值