其他 / 發散思維

(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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章