其他 / 发散思维

(1)剑指17 打印从1到最大的n位数

法1:常规解法

class Solution {
public:
    vector<int> printNumbers(int n) {
        vector<int> res;
        int max=pow(10,n);
        for(int i=1; i<max; i++){
            res.push_back(i);
        }
        return res;
    }
};

法2:用iota

用法:
        std::vector<int> foo;// 构造一个 vector 对象
        foo.resize(15);        
        std::iota(foo.begin(), foo.end(), 9);// 将从 9 开始的 15 次递增值赋值给 foo
//输出结果:9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
class Solution {
public:
    vector<int> printNumbers(int n) {
        int max = pow(10, n) - 1;
        vector<int> res(max);
       
        //res.resize(max);//改变容器大小
        iota(res.begin(), res.end(), 1);//从1开始,添加max个数字
        return res;

    }
};

法3:大数问题(没懂)

(2)剑指43. 1~n整数中1出现的次数【中等,我觉得hard】

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

示例 1:

输入:n = 12
输出:5
示例 2:

输入:n = 13
输出:6

思路:找规律

设N = abcde ,其中abcde分别为十进制中各位上的数字。
如果要计算百位上1出现的次数,它要受到3方面的影响:
百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字。

① 如果百位上数字为0,百位上可能出现1的次数由更高位决定。
比如:12013,则可以知道百位出现1的情况可能是:
100~199,1100~1199,2100~2199,,...,11100~11199,一共1200个。
可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。

② 如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。
比如:12113,则可以知道百位受高位影响出现的情况是:
100~199,1100~1199,2100~2199,,....,11100~11199,一共1200个。
和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。
但同时它还受低位影响,百位出现1的情况是:12100~12113,一共114个,
等于低位数字(113)+1。

③ 如果百位上数字大于1(2~9),则百位上出现1的情况仅由更高位决定,
比如12213,则百位出现1的情况是:
100~199,1100~1199,2100~2199,...,11100~11199,12100~12199,一共有1300个,
并且等于更高位数字+1(12+1)乘以当前位数(100)。
class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int count = 0;//1的个数
        int i = 1;//当前位
        int current = 0,after = 0,before = 0;
        while((n/i)!= 0){           
            current = (n/i)%10; //当前位数字
            before = n/(i*10); //高位数字
            after = n-(n/i)*i; //低位数字
            //如果为0,出现1的次数由高位决定,等于高位数字 * 当前位数
            if (current == 0)
                count += before*i;
            //如果为1,出现1的次数由高位和低位决定,高位*当前位+低位+1
            else if(current == 1)
                count += before * i + after + 1;
            //如果大于1,出现1的次数由高位决定,//(高位数字+1)* 当前位数
            else{
                count += (before + 1) * i;
            }    
            //前移一位
            i = i*10;
        }
        return count;
    }
};

(3)剑指62 圆圈中最后剩下的数字(约瑟夫环问题)(记)

不会,记住?
解释 https://blog.csdn.net/u011500062/article/details/72855826

int lastRemaining(int n, int m){
    int p=0;//只有1个人的情况下,胜利者下标为0
    for(int i=2;i<=n;i++)//从2个人开始依次用公示推出有i个人的情况下,胜利者下标p
        p=(p+m)%i; //由下面可以推出,i个人时最终胜利者3的下标的规律
   
    return p;
    
    //下标:0 1 2 3 4 
    //数据:
    //     0 1 2 3 4 
    //     3 4 0 1
    //     1 3 4
    //     1 3
    //     3
}

(4)剑指64 求1+2+…+n

求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

示例 1:

输入: n = 3
输出: 6
示例 2:

输入: n = 9
输出: 45

思路:&&短路运算

区别:
1意思不同: &&是“与”的意思,||是“或者”的意思。
2 使用上不同:a && b:a和b同时为true 才返回 true, 否则返回false;a || b:a或b任意一个为true 就返回true , 否则返回false
3 两者都表示运算,但是&&运算符第一个表达式不成立的话,后面的表达式不运算,直接返回。而&对所有表达式都得判断。

class Solution {
public:
    int Sum_Solution(int n) {
        int ans = n;
        ans && (ans += Sum_Solution(n - 1));
        return ans;
    }
};

(5)剑指65 不用加减乘除做加法(记)

俗话说的好:这题位运算还是背下来吧,毕竟位运算这种模拟加法用法基本就这题,很容易就忘掉。

13+11 =;
13 的二进制 1 1 0 1 -----a 13
11 的二进制 1 0 1 1 -----b 11

(a&b) <<1 -> 1 0 0 1 0 -----d 18
a^b -> 0 1 1 0 -----e 6

(d&e) <<1 -> 0 0 1 0 0 ------f 4
d^e -> 1 0 1 0 0 -----g 20

(f&g) <<1 -> 0 1 0 0 0 ------h 8
f^g -> 1 0 0 0 0 ------i 16

(h&i) <<1 -> 0 0 0 0 0 ------h 0 ---- --------退出循环
h^i -> 1 1 0 0 0 ------i 24
class Solution {
public:
    int add(int a, int b) {
        while(b!=0){
            int tmp1=a^b;
            // 注意LC c++不支持负值左移,需要强制转换为无符号数 
            int tmp2=(unsigned int)(a&b)<<1;
            a=tmp1;
            b=tmp2;
        }
        return a;
    }
};

你可能感兴趣的:(LeetCode)