補(bǔ)充

八皇后

題目:在8×8格的國(guó)際象棋上擺放八個(gè)皇后,使其不能互相攻擊掉盅,即任意兩個(gè)皇后都不能處于同一行也拜、同一列或同一斜線上,問(wèn)有多少種擺法趾痘。

想法1:一層層來(lái)放置慢哈。
代碼1:

int que[8]={-1,-1,-1,-1,-1,-1,-1,-1};
int cou=0;
bool avl(int i,int j){
        for(int m =0; m<i;m++){
            if(que[m]==j) return false;
            if((m-i)==(que[m]-j)) return false;
            if((m-i)==(j-que[m])) return false;
    }
    return true;
}
void fin(int cow){
    for(int i = 0;i<8;i++){
        que[cow]=i;
        if(avl(cow,i)){
            if(cow==7){//如果八個(gè)皇后都放滿(mǎn)了統(tǒng)計(jì)一下
            for(int i = 0 ; i<8;i++){
                cout<<que[i];
            }
             cout<<" "<<endl;
                    cou++;
            }
            fin(cow+1);
        }
    }
    return;
}

結(jié)果1:
92種方法。

剪繩子

題目:給你一根長(zhǎng)度為n繩子扼脐,請(qǐng)把繩子剪成m段(m岸军、n都是整數(shù),n>1并且m>1)瓦侮。每段的繩子的長(zhǎng)度記為k[0]艰赞、k[1]、……肚吏、k[m]方妖。k[0] * k[1]k[m]可能的最大乘積是多少?例如當(dāng)繩子的長(zhǎng)度是8時(shí)罚攀,我們把它剪成長(zhǎng)度分別為2党觅、3、3的三段斋泄,此時(shí)得到最大的乘積18杯瞻。
我的:不會(huì)

 int cut(int length) {
        if(length<2) return 0;
        if(length<4) return length-1;
        vector<int> temp;
        temp.push_back(0);
        temp.push_back(1);
        temp.push_back(2);
        temp.push_back(3);
        for(int i = 4 ;i<=length;i++){
                int ma = 0;
            for(int j = 1 ;j<=length/2;j++){
                ma = max(temp[j]*temp[i-j],ma);
            }
                temp.push_back(ma);
        }
        return temp.back();
    }

劍指:動(dòng)態(tài)規(guī)劃
動(dòng)態(tài)規(guī)劃求解問(wèn)題的四個(gè)特征:
①求一個(gè)問(wèn)題的最優(yōu)解;
②整體的問(wèn)題的最優(yōu)解是依賴(lài)于各個(gè)子問(wèn)題的最優(yōu)解炫掐;
③小問(wèn)題之間還有相互重疊的更小的子問(wèn)題魁莉;
④從上往下分析問(wèn)題,從下往上求解問(wèn)題募胃;

   """
    在剪繩子這個(gè)題目中旗唁,由于必須要剪一刀,因此會(huì)導(dǎo)致當(dāng)所給的繩子長(zhǎng)度是小于4的時(shí)候痹束,剪完之后的長(zhǎng)度
    小于剪之前的長(zhǎng)度检疫。但是我們?cè)谶f推的時(shí)候,例如求f(5) = max{f(1)*f(4), f(2)*f(3)} = 6
    如果令f(3)=2的話(huà)祷嘶,將導(dǎo)致遞推公式錯(cuò)誤屎媳,因此,對(duì)于小于4的輸入抹蚀,我們特殊處理剿牺。
注意不符合切割條件的輸入n,以及輸入為2环壤、3長(zhǎng)度時(shí)的結(jié)果晒来,因?yàn)轭}中規(guī)定m>1。
    """
//輸入繩子的長(zhǎng)度,輸出最大乘積 
int maxProductAfterCutting_solution1(int length) {
    if(length < 2)//因?yàn)橐箝L(zhǎng)度n>1,所以這里返回0表示輸入非法 
        return 0;
    if(length == 2)//長(zhǎng)度為2時(shí),因?yàn)橐蠹粝露螖?shù)m>1,所以最大是1x1=1 
        return 1;
    if(length == 3)//長(zhǎng)度為3時(shí),因?yàn)橐蠹粝露螖?shù)m>1,所以最大是1x2=2 
        return 2;

    //運(yùn)行至此,說(shuō)明繩子的長(zhǎng)度是>3的,這之后0/1/2/3這種子問(wèn)題最大就是其自身長(zhǎng)度
    //而不再需要考慮剪一刀的問(wèn)題,因?yàn)樗鼈兗粢坏稕](méi)有不剪來(lái)的收益高
    //而在當(dāng)下這么長(zhǎng)的繩子上剪過(guò)才可能生成0/1/2/3這種長(zhǎng)度的繩子,它們不需要再減
    //所以下面的表中可以看到它們作為子問(wèn)題的值和上面實(shí)際返回的是不一樣的 

    //在表中先打上子繩子的最大乘積 
    int* products = new int[length + 1];
    products[0] = 0;
    products[1] = 1;
    products[2] = 2;
    products[3] = 3;//到3為止都是不剪最好 

    int max = 0;//用于記錄最大乘積 
    //對(duì)于4以上的情況,每次循環(huán)要求f(i) 
    for(int i = 4; i <= length; ++i) {
        max = 0;//每次將最大乘積清空
        //因?yàn)橐?jì)算f(j)乘以f(i-j)的最大值,j超過(guò)i的一半時(shí)是重復(fù)計(jì)算
        //所以只需要考慮j不超過(guò)i的一半的情況 
        for(int j = 1; j <= i / 2; ++j) {
            //計(jì)算f(j)乘以f(i-j)
            int product = products[j] * products[i - j];
            //如果比當(dāng)前找到的還大 
            if(max < product)
                max = product;//就把最大值更新 
        }
        //這里是循環(huán)無(wú)關(guān)的,書(shū)上在for里面,我把它提出來(lái) 
        products[i] = max;//最終,更新表中的f(i)=max(f(j)·f(i-j))
    }
    //循環(huán)結(jié)束后,所求的f(length)也就求出來(lái)了 
    max = products[length];//將其記錄下來(lái)以在銷(xiāo)毀后能返回 
    delete[] products;//銷(xiāo)毀打表的輔助空間 
    return max; 
}

打印從1到最大的n位數(shù)

題目:
輸入數(shù)字n郑现,按順序打印出從1到最大的n位十進(jìn)制數(shù)湃崩。比如輸入3,則打印出1接箫、2攒读、3一直到最大的3位數(shù)即999。
我的:

//方法1:
 void print(int n) {
        int ma = 0;
        while(n!=0){
            ma = ma*10+9;
            n--;
        }
        for(int i = 1 ;i<=ma;i++){
             cout<<i<<endl;
        }
    }
//方法2:全排列
  vector<string> result;
    void all(int index, int n,string temp){
        if(index>n)
         {
            result.push_back(temp);
            return;
         }
         for(int i = 0;i<10;i++){
            string temp2 = temp+char('0'+i);
            all(index+1,n,temp2);
         }
    }
    void print(int n) {
        string str = "";
        all(1,n,str);
        string s;
        for(int j = 1 ;j<result.size();j++){
             s = result[j];
             bool flag = false;
             int i = 0;
                while(i<n){
                    if(!flag){
                        if(s[i]!='0'){
                             flag = true;
                             cout<<s[i];
                        }
                    }else{
                        cout<<s[i];
                    }
                    i++;
            }
            cout<<""<<endl;
        }
    }

劍指:

//模擬加法:
class Solution {
public:
    void Print1ToMaxOfNDigits(int n)
    {
 
        char* number = new char[n + 1];
        //開(kāi)辟一個(gè)存放字符數(shù)組(包含n + 1個(gè)元素 number[0]~number[n])的空間辛友,返回字符數(shù)組首元素的地址
        memset(number, '0', n); // number[0]~number[n-1]都是'0'
        number[n] = '\0';
 
        while (!Increment(number))
        {
            PrintNumber(number);
        }
    }
private:
    bool Increment(char* number)
    {
        //此函數(shù)用于在表示數(shù)字的字符串上 + 1薄扁,并判斷有沒(méi)有溢出
 
        //number是一個(gè)字符串
        bool isOverflow = false;      //溢出
        int nTackOver = 0;            //進(jìn)位標(biāo)志
        int nLength = strlen(number); //計(jì)算字符串str 的長(zhǎng)度剪返,直到空結(jié)束字符
                                      // number[nLength - 1]是這個(gè)數(shù)字的倒數(shù)第1位
        for (int i = nLength - 1; i >= 0; i--)
        {
            int nSum = number[i] - '0' + nTackOver;
            if (i == nLength - 1)
                nSum++;              //如果是個(gè)位(最后一位)的話(huà),+1
 
            if (nSum >= 10)
                if (i == 0)
                    isOverflow = true; //如果nSum==10,且是最高位邓梅,則溢出
                else
                {
                    nSum -= 10;
                    nTackOver = 1; //進(jìn)位
                    number[i] = '0' + nSum;
                }
            else
            {
                number[i] = '0' + nSum;
                break;    //運(yùn)行到某一數(shù)位不需要進(jìn)位脱盲,退出循環(huán)
                          // 例如520+1之后個(gè)位 nSum < 10,此時(shí)不會(huì)產(chǎn)生進(jìn)位,也不會(huì)有溢出的情況
                          //可以直接退出循環(huán)
            }
        }
        return isOverflow;
    }
    void PrintNumber(char* number) //此函數(shù)用于打印數(shù)字日缨,數(shù)字前面補(bǔ)位的“0”不打印
    {
        bool isBeginning0 = true;
        int nLength = strlen(number);
 
        for (int i = 0; i < nLength; i++)
        {
            if (isBeginning0 && number[i] != '0')//開(kāi)始不為0钱反,第i位不是0
                isBeginning0 = false;   //例如“00098”到number[2]才不是0,兩個(gè)條件都為true
                                        //isBeginning0 = false
            if (!isBeginning0)          //isBeginning0 = false才能執(zhí)行輸出
                cout << number[i];
        }
        cout << endl;
    }
};
//全排序:

class Solution {
public:
    void Print1ToMaxOfNDigits(int n)
    {
    
        char* number = new char[n + 1];
        //開(kāi)辟一個(gè)存放字符數(shù)組(包含n + 1個(gè)元素 number[0]~number[n])的空間,返回字符數(shù)組首元素的地址
        memset(number, '0', n); // number[0]~number[n-1]都是'0'
        number[n] = '\0';
 
        dfsHelper(number, 0, n);
    }
 
private:
    void PrintNumber(char* number) //此函數(shù)用于打印數(shù)字匣距,數(shù)字前面補(bǔ)位的“0”不打印
    {
        bool isBeginning0 = true;
        int nLength = strlen(number);
 
        for (int i = 0; i < nLength; i++)
        {
            if (isBeginning0 && number[i] != '0')//開(kāi)始不為0很钓,第i位不是0
                isBeginning0 = false;   //例如“00098”到number[2]才不是0,兩個(gè)條件都為true
                                    //isBeginning0 = false
            if (!isBeginning0)          //isBeginning0 = false才能執(zhí)行輸出
                cout << number[i];
        }
        cout << endl;
    }
 
    void dfsHelper(char* number, int index, int n)
    {
        if (index == n)
        {
            PrintNumber(number);
            return;
        }
 
        for (int i = 0; i < 10; i++)
        {
            number[index] = i + '0';
            dfsHelper(number, index + 1, n);
        }
 
    }
 
 
};

刪除鏈表的節(jié)點(diǎn)

題目:在O(1)時(shí)間內(nèi)刪除鏈表節(jié)點(diǎn)水由。
我的:遍歷在刪除是O(N)
由于給出了所要?jiǎng)h除結(jié)點(diǎn)指針,所以可以直接考慮用刪除結(jié)點(diǎn)的下一結(jié)點(diǎn)代替要?jiǎng)h除的結(jié)點(diǎn),然后釋放要?jiǎng)h除結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)补疑。這里得注意的是需要考慮要?jiǎng)h除結(jié)點(diǎn)的三種情況:1.要?jiǎng)h除的節(jié)點(diǎn)不是尾節(jié)點(diǎn)走芋,2.鏈表只有一個(gè)節(jié)點(diǎn)骤铃,刪除頭結(jié)點(diǎn)(也是尾節(jié)點(diǎn))3.鏈表中有多個(gè)節(jié)點(diǎn)沛善,刪除尾結(jié)點(diǎn)(這里的情況就蛻變成一般從頭到尾遍歷尋找要?jiǎng)h除的節(jié)點(diǎn)的思路,開(kāi)始沒(méi)注意到給出要?jiǎng)h除的結(jié)點(diǎn)的指針已經(jīng)給出驶乾,考慮到了這個(gè)O(N)算法...)

劍指:

void DeletNode(ListNode** pListHead,ListNode* pToBeDeleted)//傳遞二級(jí)指針的原因邑飒,可能會(huì)修改頭節(jié)點(diǎn)
{
    if(!pListHead||pToBeDeleted)
        return;
    //要?jiǎng)h除的節(jié)點(diǎn)不是尾節(jié)點(diǎn)
    if(pToBeDeleted->m_pNext!=nullptr)
    {
        ListNode* pNext=pToBeDeleted->m_pNext;
        pToBeDeleted->m_nValue=pNext->m_nValue;
        pToBeDeleted->m_pNext=pNext->m_pNext;
        
        delete pNext;
        pNext=nullptr;
    }
    //鏈表只有一個(gè)節(jié)點(diǎn),刪除頭節(jié)點(diǎn)(也是尾節(jié)點(diǎn))
    else if(*pListHead==pToBeDeleted)
    {
        delete pToBeDeleted;
        pToBeDeleted=nullptr;
        *pListHead=nullptr;
    }
    //鏈表中有多個(gè)節(jié)點(diǎn)级乐,刪除尾節(jié)點(diǎn)
    else
    {
        ListNode* pNode=*pListHead;
        while(pNode->m_pNext!=pToBeDeleted)
        {
            pNode=pNode->m_pNext;
        }
        pNode->m_pNext=nullptr;
        delete pToBeDeleted;
        pToBeDeleted=nullptr;
    }

數(shù)字序列中某一位的數(shù)字

題目:
數(shù)字以01234567891011121314...的格式排列疙咸。在這個(gè)序列中,第5位(從0開(kāi)始計(jì))是5风科,第13位是1撒轮,第19位是4。求任意第n為對(duì)應(yīng)的數(shù)字贼穆。

我的:

    int num(int n){
        if(n==0) return 0;
        if(n==1) return 10;
        return (pow(10,n)-pow(10,n-1))*n;
    }
    void test(int index) {
        int n = 0;
        int sum = 0;
        while(index+1>sum){
            sum+=num(++n);
        }
        sum = 0;
        int temp = n-1;
        while(temp>0){
            sum+=num(temp--);
        }
        int temp2;
        if(n==1) temp2 = (index-sum)/n;
        else temp2 = pow(10,n-1)+(index-sum)/n;
        cout<<to_string(temp2)[index%n]<<endl;
    }

//方法2:
    int num(int n){
        if(n==0) return 0;
        if(n==1) return 10;
        return (pow(10,n)-pow(10,n-1))*n;
    }
    void test(int index) {
        int n = 0;
        int sum = 0;
        while(index+1>sum){
            sum+=num(++n);
        }
        sum = 0;
        int temp = n-1;
        while(temp>0){
            sum+=num(temp--);
        }
        int temp2;
        if(n==1) temp2 = (index-sum)/n;
        else temp2 = pow(10,n-1)+(index-sum)/n;
        for(int i = 0;i<n-index%n-1;i++){
            temp2=temp2/10;
        }
        temp2=temp2%10;
        cout<<temp2<<endl;
    }

劍指:

以第15位數(shù)字2為例(2隸屬與12题山,兩位數(shù),位于12從左側(cè)以0號(hào)開(kāi)始下標(biāo)為1的位置)
步驟1:首先確定該數(shù)字是屬于幾位數(shù)的;
      如果是一位數(shù)故痊,n<9;如果是兩位數(shù)顶瞳,n<9+90*2=189;
      說(shuō)明是兩位數(shù)。
步驟2:確定該數(shù)字屬于哪個(gè)數(shù)愕秫。10+(15-10)/2= 12慨菱。
步驟3:確定是該數(shù)中哪一位。15-10-(12-10)*2 = 1, 所以位于“12”的下標(biāo)為1的位置戴甩,即數(shù)字2符喝。

以第1001位數(shù)字7為例
步驟1:首先確定該數(shù)字是屬于幾位數(shù)的;
      如果是一位數(shù),n<9;如果是兩位數(shù)甜孤,n<9+90*2=189;如果是三位數(shù)协饲,n<189+900*3=2889;
      說(shuō)明是三位數(shù)畏腕。
步驟2:確定該數(shù)字屬于哪個(gè)數(shù)。100+(1001-190)/3= 370茉稠。
步驟3:確定是該數(shù)中哪一位郊尝。1001-190-(370-100)*3 = 1,所以位于“370”的下標(biāo)為1的位置,即數(shù)字7战惊。


禮物的最大值

題目:
?在一個(gè) m*n 的棋盤(pán)中的每一個(gè)格都放一個(gè)禮物,每個(gè)禮物都有一定的價(jià)值(價(jià)值大于0).你可以從棋盤(pán)的左上角開(kāi)始拿各種里的禮物扎即,并每次向左或者向下移動(dòng)一格吞获,直到到達(dá)棋盤(pán)的右下角。給定一個(gè)棋盤(pán)及上面?zhèn)€的禮物谚鄙,請(qǐng)計(jì)算你最多能拿走多少價(jià)值的禮物各拷?

比如說(shuō)現(xiàn)在有一個(gè)如下的棋盤(pán),


image.png

在這個(gè)棋盤(pán)中闷营,按照(1烤黍,12,5傻盟,7速蕊,7,16娘赴,5)的順序可以拿到總價(jià)值最大的禮物规哲。


image.png

我的:

//方法1:
 int ma = 0;
    void dp(vector<vector<int>> in , int nrows, int ncols,int rows, int cols, int sum){
         if(nrows>rows-1||ncols>cols-1) return;
         if(nrows==rows-1&&ncols==cols-1) {
            sum+=in[nrows][ncols];
            ma = max(ma, sum);
            return;
         }
         sum+=in[nrows][ncols];
         dp(in, nrows+1,ncols,rows,cols,sum);
         dp(in, nrows,ncols+1,rows,cols,sum);
    }
    void test(vector<vector<int>> in , int rows, int cols) {
        int sum = 0;
         dp(in, 0,0,rows,cols,sum);
         cout<<ma<<endl;
    }
//方法2:每個(gè)格子等于max(左,上)+本身诽表,而且只用維護(hù)一維列長(zhǎng)的數(shù)組唉锌,保存結(jié)果。
 int test(vector<vector<int>> in , int rows, int cols) {
        if(rows==0||cols==0) return 0;
        int result = 0;
        vector<int> flag(cols,0);
        int temp = 0;
        flag[0] = in[0][0];
        for(int i = 0 ;i<rows;i++){
            for(int j = 0 ;j<cols;j++){
                    int left = j-1>=0?flag[j-1]:0;
                    int up = i-1>=0?flag[j]:0;
                flag[j] = max(left, up)+in[i][j];
            }
        }
        return flag[cols-1];
    }

劍指:方法2

最長(zhǎng)不含重復(fù)字符的子字符串

題目:請(qǐng)從字符串中找出一個(gè)最長(zhǎng)的不包含重復(fù)字符的子字符串竿奏,計(jì)算該最長(zhǎng)子字符串的長(zhǎng)度袄简。假設(shè)字符串中只包含從’a’到’z’的字符。例如泛啸,在字符串中”arabcacfr”绿语,最長(zhǎng)非重復(fù)子字符串為”acfr”,長(zhǎng)度為4候址。
我的:不會(huì)

//動(dòng)規(guī):f(i)表示當(dāng)前字符為結(jié)尾的最大子串長(zhǎng)度
 int test(string str) {
        int length = str.size();
        if(length<2) return length;
        vector<int> flag(26,-1);
        vector<int> result(length,0);
        int ma = 0;
        for(int i = 0 ;i < length;i++){
            if(flag[str[i]-'a']<0){
                flag[str[i]-'a']=i;
                if(i>0)result[i] = result[i-1]+1;
                else result[i]++;
            }else{
                int dif = i - flag[str[i]-'a'];
                if(dif<= result[i-1]){
                    result[i] = dif;
                }else{
                    result[i] = result[i-1]+1;
                }
                flag[str[i]-'a']=i;
            }
            ma = max(ma, result[i]);
        }
        return ma;
    }
//方法2:雙指針汞舱,左到右,start表示開(kāi)始位置
  int lengthOfLongestSubstring(string s) {
        vector<int> dict(256, -1); // 用來(lái)記錄字符上次出現(xiàn)的位置
        int maxlen=0, start = -1;
        for (int i = 0; i != s.length(); i++){
            // s[i]字符上次出現(xiàn)的下標(biāo)是否在start之后宗雇,若是昂芜,則重復(fù)了,則修改start為上一次s[i]的位置赔蒲,從它后一位開(kāi)始搜索
            if (dict[s[i]] > start)  
                start = dict[s[i]];
            dict[s[i]] = i;
            maxlen = max(maxlen, i - start);
        }
        return maxlen;
    }

劍指:

//動(dòng)規(guī):
int test(string str) {
        int length = str.size();
        if(length<2) return length;
        vector<int> flag(26,-1);
        int currentLength = 0;
        int ma = 0;
        for(int i = 0 ;i < length;i++){
            if(flag[str[i]-'a']<0){
                flag[str[i]-'a']=i;
                currentLength++;
            }else{
                int dif = i - flag[str[i]-'a'];
                if(dif <= currentLength){
                    currentLength = dif;
                }else{
                    currentLength++;
                }
                flag[str[i]-'a']=i;
            }
            ma = max(ma, currentLength);
        }
        return ma;
    }

N個(gè)骰子的點(diǎn)數(shù)

題目: 把n個(gè)骰子扔在地上泌神,所有骰子朝上一面的點(diǎn)數(shù)之和為s良漱,
輸入n,打印出s的所有可能的值出現(xiàn)的概率欢际。

n個(gè)骰子的總點(diǎn)數(shù)母市,最小為n,最大為6n损趋,根據(jù)排列組合的知識(shí)患久,那個(gè)骰子,所有點(diǎn)數(shù)的排列數(shù)為6^n浑槽。
我們先統(tǒng)計(jì)每一個(gè)點(diǎn)數(shù)出現(xiàn)的次數(shù)蒋失,然后把每一個(gè)點(diǎn)數(shù)出現(xiàn)的次數(shù)除以6^n,就能求出每個(gè)點(diǎn)數(shù)出現(xiàn)的概率桐玻。
我的:

//遞歸:算出每個(gè)和的個(gè)數(shù)篙挽,5n個(gè)和
  void dp( vector<int>& flag ,int nn, int n,int sum){
         if(nn>n) {
            flag[sum-n]++;
            return;
         }
        for(int i = 1;i<7;i++){
            sum += i;
            dp(flag,nn+1,n,sum);
            sum -= i;
        }
    }
    vector<double> test(int n) {
        vector<double> result;
        if(n<1) return result;
         vector<int > flag(5*n+1,0);
        dp(flag, 1, n , 0);
        for(int i : flag){
             result.push_back(i/pow(6,n));
        }

        return result;
    }

劍指:

思路一:
    基于遞歸求骰子點(diǎn)數(shù),時(shí)間效率不夠高镊靴。
先把骰子分成兩堆铣卡,第一堆只有一個(gè),第二堆有n-1個(gè)偏竟,
單獨(dú)的那一個(gè)可能出現(xiàn)1到6的點(diǎn)數(shù)煮落,我們需要計(jì)算從1-6的每一種點(diǎn)數(shù)和剩下的n-1個(gè)骰子來(lái)計(jì)算點(diǎn)數(shù)和。
還是把n-1個(gè)那部分分成兩堆踊谋,上一輪的單獨(dú)骰子點(diǎn)數(shù)和這一輪的單獨(dú)骰子點(diǎn)數(shù)相加州邢,然后再和剩下的n-2個(gè)骰子來(lái)計(jì)算點(diǎn)數(shù)和。
不難發(fā)現(xiàn)這是一種遞歸的思路褪子。
    定義一個(gè)長(zhǎng)度為6n-n+1的數(shù)組量淌,和為s的點(diǎn)數(shù)出現(xiàn)的次數(shù)保存到數(shù)組的第s-n個(gè)元素里。
    
#include <iostream>
#include <cstdio>

using namespace std;

int g_maxValue = 6;

void Probability(int original, int current, int sum, int *pProbabilities)
{
    if (current == 1)
    {
        pProbabilities[sum - original]++;
    }
    else
    {
        for (int i = 1; i <= g_maxValue; ++i)
        {
            Probability(original, current - 1, i + sum, pProbabilities);
        }
    }
}

void Probability(int number, int *pProbabilities)
{
    for (int i = 1; i <= g_maxValue; ++i)
    {
        Probability(number, number, i, pProbabilities);
    }
}

void PrintProbability(int number)
{
    if (number < 1)
    {
        return;
    }
    int maxSum = number * g_maxValue;
    int *pProbabilities = new int[maxSum - number + 1];
    for (int i = number; i <= maxSum; ++i)
    {
        pProbabilities[i - number] = 0;
    }

    Probability(number, pProbabilities);

    int total = pow( (double)g_maxValue, number);
    for (int i = number; i <= maxSum; ++i)
    {
        double ratio = (double)pProbabilities[i - number] / total;
        printf("%d: %e\n", i, ratio);
    }
    delete[] pProbabilities;
}

int main()
{
    PrintProbability(6);
    return 0;
}
 
思路二:
    基于循環(huán)求骰子點(diǎn)數(shù)嫌褪,時(shí)間性能好呀枢。
用兩個(gè)數(shù)組來(lái)存儲(chǔ)骰子點(diǎn)數(shù)的每一種出現(xiàn)的次數(shù)。
在一次循環(huán)中笼痛,第一個(gè)數(shù)組中的第n個(gè)數(shù)字表示骰子和為n出現(xiàn)的次數(shù)裙秋。
在下一次循環(huán)中我們加上一個(gè)新的骰子,此時(shí)和為n的骰子出現(xiàn)的次數(shù)應(yīng)該等于上一次循環(huán)中骰子點(diǎn)數(shù)和為n-1缨伊、n-2摘刑、n-3、n-4刻坊、n-5與n-6的次數(shù)的綜合枷恕,所以我們把另一個(gè)數(shù)組的第n個(gè)數(shù)字設(shè)為前一個(gè)數(shù)組對(duì)應(yīng)的第n-1、n-2谭胚、n-3徐块、n-4未玻、n-5與n-6之和。
#include <iostream>
#include <cstdio>

using namespace std;

int g_maxValue = 6;

void PrintProbability(int number)
{
    if (number < 1)
    {
        return ;
    }
    int *pProbabilities[2];
    pProbabilities[0] = new int[g_maxValue * number + 1];
    pProbabilities[1] = new int[g_maxValue * number + 1];
    for (int i = 0; i < g_maxValue; ++i)
    {
        pProbabilities[0][i] = 0;
        pProbabilities[1][i] = 0;
    }

    int flag = 0;
    for (int i = 1; i <= g_maxValue; ++i)
    {
        pProbabilities[flag][i] = 1;
    }

    for (int k = 2; k <= number; ++k)
    {
        for (int i = 0; i < k; ++i)
        {
            pProbabilities[1 - flag][i] = 0;
        }

        for (int i = k; i <= g_maxValue * k; ++i)
        {
            pProbabilities[1 - flag][i] = 0;
            for (int j = 1; j <= i && j <= g_maxValue; ++j)
            {
                pProbabilities[1 - flag][i] += pProbabilities[flag][i - j];
            }
        }
        flag = 1 - flag;
    }
    double total = pow( (double)g_maxValue, number);
    for (int i = number; i <= g_maxValue * number; ++i)
    {
        double ratio = (double)pProbabilities[flag][i] / total;
        printf("%d: %e\n", i, ratio);
    }
    delete[] pProbabilities[0];
    delete[] pProbabilities[1];
}

int main()
{
    PrintProbability(6);
    return 0;
}

股票的最大利潤(rùn)

題目:假設(shè)把某股票的價(jià)格按照時(shí)間先后順序存儲(chǔ)在數(shù)組中胡控,請(qǐng)問(wèn)買(mǎi)賣(mài)該股票一次可獲得的最大利潤(rùn)是多少扳剿?例如,一只股票在某些時(shí)間節(jié)點(diǎn)的價(jià)格為{9,11,8,5,7,12,16,14}昼激。如果我們能在價(jià)格為5的時(shí)候買(mǎi)入并在價(jià)格為16時(shí)賣(mài)出庇绽,則能獲得最大的利潤(rùn)為11.

我的:

//方法1:雙指針 
    int test(vector<int> in) {
        int length = in.size();
        if(length<2) return 0;
        int mi = in[0];
        int ma = INT_MIN;
        for(int i = 1;i<length;i++){
            mi = min(mi,in[i]);
            ma = max(ma, in[i] - mi);
        }
        return ma;
    }
//方法2:動(dòng)規(guī),當(dāng)前這個(gè)東西的最優(yōu)解
  int test(vector<int> in) {
        int length = in.size();
        if(length<2) return 0;
        vector<int> flag(length,0);
        int mi = in[0];
        for(int i = 1;i<length;i++){
            mi = min(mi,in[i]);
            flag[i] = in[i]- mi>flag[i-1]?in[i]- mi:flag[i-1];
        }
        return flag[length-1];
    }

劍指:方法1

背包問(wèn)題

題目:
(1)經(jīng)典的0-1背包問(wèn)題(無(wú)物品的價(jià)值):

假設(shè)有一個(gè)能裝入容量為C的背包和n件重量分別為w1,w2,,...,wn的物品橙困,能否從n件物品中挑選若干件恰好裝滿(mǎn)背包,要求找出所有滿(mǎn)足上述條件的解瞧掺。

當(dāng)C=10,各件物品重量為{1,8,4,3,5,2}時(shí),可以找到下列4組解:(1,4,3,2)纷宇、(1,4,5)、(8,2)和(3,5,2)蛾方。
我的:

//方法1:
 void bag( vector<vector<int>>& result,vector<int> temp,int index, int sum ,int c, vector<int> in){
        if(index>=in.size()){
            if(sum==c) {
                result.push_back(temp);
            }
               return;
        }
            if(sum+in[index]<=c){
                temp.push_back(in[index]);
                bag(result,temp,index+1, sum+in[index], c, in);
                temp.pop_back();
            }
            bag(result,temp,index+1, sum, c, in);
    }
    vector<vector<int>> test(vector<int> in, int c) {
        int length = in.size();
         vector<vector<int>> result;
        if(length<1) return result;
        vector<int> temp;
        bag(result,temp,0 , 0 , c,in);
        return result;
    }

(2)經(jīng)典的0-1背包問(wèn)題(有物品的價(jià)值):

給定n種物品和一個(gè)背包像捶。物品i的重量是wi,其價(jià)值為vi桩砰,背包的容量為C拓春。應(yīng)該如何選擇裝入背包中的物品,使得裝入背包中物品的總價(jià)值最大亚隅?
我的:不對(duì)硼莽,不一定放滿(mǎn),用的是回溯煮纵?懂鸵,不是動(dòng)規(guī),蠻力法求解0/1背包問(wèn)題的時(shí)間復(fù)雜度為:2^n

 int ma = 0;
    void bag( vector<vector<int>>& result,vector<int> temp,int index, int sum ,int valsum ,int c, vector<int> in,vector<int> in2){
        if(index>=in.size()){
            if(sum==c) {
                if(ma<valsum){
                    ma= valsum;
                     result.push_back(temp);
                }
            }
               return;
        }
            if(sum+in[index]<=c){
                temp.push_back(in[index]);
                bag(result,temp,index+1, sum+in[index],valsum+in2[index], c, in,in2);
                temp.pop_back();
            }
            bag(result,temp,index+1, sum,valsum, c, in, in2);
    }
    vector<vector<int>> test(vector<int> in, vector<int> in2,int c) {
        int length = in.size();
         vector<vector<int>> result;
        if(length<1) return result;
        vector<int> temp;
        bag(result,temp,0 , 0 ,0, c,in,in2);
        return result;
    }

動(dòng)規(guī):


image.png
  int test(vector<int> zhong, vector<int> value,int n, int c) {
        int length = zhong.size();
        if(length<1) return 0;
        vector<vector<int>> flag(n+1 ,vector<int>(c+1));
        for(int i = 1;i<=n;i++){
            for(int j = 1;j<=c;j++){
                if(zhong[i-1]>j) flag[i][j] = flag[i-1][j];
                else{
                    flag[i][j] = max(flag[i-1][j],flag[i-1][j-zhong[i-1]]+value[i-1]);
                }
            }
        }
    for(int i = n,j = C; i > 0; i--){  //找出放入的物品
        if(V[i][j] > V[i-1][j]){
            x[i-1] = 1;
            j = j - a[i-1].wight;
        }
        else
            x[i-1] = 0;
        return flag[n][c];
    }

236. Lowest Common Ancestor of a Binary Tree

題目:
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]

image

Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.

Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

Note:

  • All of the nodes' values will be unique.
  • p and q are different and both values will exist in the binary tree.
  bool dfs(TreeNode* root,TreeNode* p, vector<TreeNode*>& temp){
       temp.push_back(root);
       if(root == p) return true;
       if(root->left!=NULL) {
            if(dfs(root->left, p, temp)) return true;
             temp.pop_back();
       }
       if(root->right!=NULL){
            if(dfs(root->right, p, temp)) return true;
             temp.pop_back();
       }
       return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL||p==NULL||q==NULL) return NULL;
        vector<TreeNode*> temp1;
        vector<TreeNode*> temp2;
        if(dfs(root, p, temp1)&&dfs(root, q, temp2)){
            for(int i = 0;i<temp1.size()&&i<temp2.size();i++){

                if(temp1[i]!=temp2[i]){
                    return temp1[i-1];
                }
               if(temp1[i]==p){
                    return temp1[i];
                }
                 if(temp2[i]==q){
                    return temp2[i];
                }
            }
        }
        return NULL;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末行疏,一起剝皮案震驚了整個(gè)濱河市匆光,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌酿联,老刑警劉巖终息,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贞让,居然都是意外死亡周崭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)喳张,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)续镇,“玉大人,你說(shuō)我怎么就攤上這事销部∧ト。” “怎么了人柿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)忙厌。 經(jīng)常有香客問(wèn)我凫岖,道長(zhǎng),這世上最難降的妖魔是什么逢净? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任哥放,我火速辦了婚禮,結(jié)果婚禮上爹土,老公的妹妹穿的比我還像新娘甥雕。我一直安慰自己,他們只是感情好胀茵,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布社露。 她就那樣靜靜地躺著,像睡著了一般琼娘。 火紅的嫁衣襯著肌膚如雪峭弟。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天脱拼,我揣著相機(jī)與錄音瞒瘸,去河邊找鬼。 笑死熄浓,一個(gè)胖子當(dāng)著我的面吹牛情臭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赌蔑,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼俯在,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了娃惯?” 一聲冷哼從身側(cè)響起朝巫,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎石景,沒(méi)想到半個(gè)月后劈猿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡潮孽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年揪荣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片往史。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仗颈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挨决,我是刑警寧澤请祖,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站脖祈,受9級(jí)特大地震影響肆捕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盖高,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一慎陵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喻奥,春花似錦席纽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至甥厦,卻和暖如春纺铭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背矫渔。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工彤蔽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摧莽,地道東北人庙洼。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像镊辕,于是被迫代替她去往敵國(guó)和親油够。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容