1. 程式人生 > >初識Leetcode----學習(二十一)【打家劫舍、快樂數】

初識Leetcode----學習(二十一)【打家劫舍、快樂數】

打家劫舍

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警

給定一個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

示例 1:

輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。
     偷竊到的最高金額 = 1 + 3 = 4 。

示例 2:

輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接著偷竊 5 號房屋 (金額 = 1)。
     偷竊到的最高金額 = 2 + 9 + 1 = 12 。

1.考慮動態規劃解決,假設輸入的例項為[2,7,9,3,1],dp[i]為打劫i家所能得到的最大財富,首先dp[0]肯定為2,然後再分析dp[1],從前兩家找出比較大的,易得dp[1]為7,然後關鍵在於推匯出狀態轉移方程,當打劫3家時,就要考慮如何才能使得打劫到的財富最多,根據題意,不能打劫相鄰的兩家,就只剩兩種情況,一種為nums[0] + nums[2],另一種為dp[1],然後再這兩種中選擇最優的一種,就可以得到狀態轉移方程為: dp[i] = max(dp[i-2] + nums[i], dp[i-1]);,據此可寫出程式碼:

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() <= 1)
            return !nums.empty() ? nums[0] : 0;    //如果為空,返回0;否則返回nums[0]
        vector<int> dp{nums[0], max(nums[0], nums[1])};  //初始化dp[0],dp[1]
        for (int i = 2; i < nums.size(); ++i)
        {
            dp.push_back(max(nums[i] + dp[i - 2], dp[i-1]));   //寫狀態轉移方程
        } 
        return dp.back();
    }
};

2.還是動態規劃的思想,利用兩個變數sum1、sum2,通過奇偶來更新sum1、sum2(確保不會相鄰),返回a、b中的更大值:

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.empty())
            return 0;
        int sum1 = 0, sum2 = 0;
        for (int i = 0;i < nums.size(); ++i)
        {
            if (i % 2 == 0)
                sum1 = max(sum1 + nums[i],sum2);
            else
                sum2 = max(sum1, sum2 + nums[i]);
        }
        return max(sum1,sum2);
    }
};

 

 

 

快樂數

編寫一個演算法來判斷一個數是不是“快樂數”。

一個“快樂數”定義為:對於一個正整數,每一次將該數替換為它每個位置上的數字的平方和,然後重複這個過程直到這個數變為 1,也可能是無限迴圈但始終變不到 1。如果可以變為 1,那麼這個數就是快樂數。

示例: 

輸入: 19
輸出: true
解釋: 
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1:

1.判斷是否出現迴圈,比如當a進行判斷是否是快樂數,若後續計算中又出現了a則說明有迴圈存在,足以證明a不是快樂數:

class Solution {
public:
    bool isHappy(int n) {
        set<int> st;   //儲存計算中的數字
        while (n != 1)
        {
            n = cal(n);  //呼叫函式計算平方和
            if (st.count(n))    //如果同一個數字出現不止一次則說明不是快樂數
                return false;
            st.insert(n);       //將計算的數存入set
        }
        return true;
    }
    int cal(int n)           //計算當前數字的各個位的平方和
    {
        int sum = 0;
        while (n > 0)
        {
            sum += pow(n%10, 2);
            n /= 10;
        }
        return sum;
    }
};

2.關於非快樂數有個特點,就迴圈的數字必定有4,這種思路參考Grandyang的部落格,證明什麼的不會呀:

class Solution {
public:
    bool isHappy(int n) {
        while (n != 1 && n != 4)
        {
            int sum = 0;
            while (n > 0)
            {
                sum += pow(n%10, 2);
                n /= 10;
            }
            n = sum;
        }
        return n == 1;
    }
};