Leetcode (213)| 打家劫舍 2

微信公衆號:Jerry的算法和NLPpython

| 題目

你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有必定的現金。這個地方全部的房屋都圍成一圈,這意味着第一個房屋和最後一個房屋是緊挨着的。同時,相鄰的房屋裝有相互連通的防盜系統,若是兩間相鄰的房屋在同一夜被小偷闖入,系統會自動報警。正則表達式

給定一個表明每一個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的狀況下,可以偷竊到的最高金額。算法

| examlple:

示例 1:數組

1輸入: [2,3,2]
2輸出: 3
3解釋: 你不能先偷竊 1 號房屋(金額 = 2),而後偷竊 3 號房屋(金額 = 2), 由於他們是相鄰的。

示例 2:微信

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

| 分析:

這應該是動態規劃的一道比較中等的題目了,上一次講到的題目是他的弟弟:
Leetcode (198)| 打家劫舍
考慮全部可能的搶劫方案過於困難,並且複雜度必定會超時數據結構

抓住題目中的條件,

  • 相鄰兩個房屋不能同時偷竊
  • 房屋之間造成了一個環

這意味着要搶第一個屋,最後一個屋就不能搶
搶最後一個屋,第一個屋就不能搶
並且搶了這個第N個屋子,N+1和N-1的屋子也不能搶機器學習

Leetcode (213)| 打家劫舍 2

首先考慮下Base case
n=0 return 0
n=1 return nums[0]
n=2 假設爲a,b要麼搶a 要麼搶b return max(nums)
n=3 假設爲a,b,c 要麼搶a,要麼b,要麼c return max(nums)ide

n=4 假設爲a,b,c,d
若是我一開始打算搶a,那麼d我是夠不着了,因此我只能從a,b,c裏進行遞歸
若是我一開始不打算搶b,那麼d是在我考慮的範圍內,我從b,c,d裏進行挑選函數

對於 n >=4,有兩個選項:
搶第1個房子,去掉最後一個房子。
不搶第1個房子,保留最後一個房子。
顯然,你想選擇數額更大的選項。因而,能夠總結出公式:
Leetcode (213)| 打家劫舍 2學習

因此你只須要考慮兩種狀況,而後就兩種狀況的最大值取最大便可。

代碼:

python

1class Solution:
 2    def rob(self, nums: List[int]) -> int:
 3        if not nums:
 4            return 0
 5        if len(nums)<=3:
 6            return max(nums)
 7        if len(nums)==4:
 8            return max(nums[0]+nums[2],nums[1]+nums[3])
 9        step=[0 for i in range(len(nums))]
10        step[0],step[1],step[2]=nums[0],nums[1],nums[0]+nums[2]
11        for i in range(3,len(nums)-1):
12            step[i]=max(step[i-2],step[i-3])+nums[i]
13        temp=max(step)
14        step=[0 for i in range(len(nums))]
15        step[1],step[2],step[3]=nums[1],nums[2],nums[1]+nums[3]
16        for j in range(4,len(nums)):
17            step[j]=max(step[j-2],step[j-3])+nums[j]
18        temp2=max(step)
19        return max(temp,temp2)

C++

1int rob(vector<int>& nums)
 2{
 3    if (nums.size() == 1) return nums[0];
 4
 5    int sumOdd[2] = {0, 0}; // 0 == head, 1 == tail
 6    int sumEven[2] = { 0, 0 };
 7    for (int i = 0; i < nums.size(); i++)
 8    {
 9        for (int j = 0; j < 2; j++)
10        {
11            if (i == 0 && j == 1) continue; // head only
12            if (i == nums.size() - 1 && j == 0) continue;   // tail only
13            if (i % 2 == 0)
14            {
15                sumOdd[j] = max(sumOdd[j], sumEven[j]);
16                sumEven[j] += nums[i];
17            }
18            else
19            {
20                sumEven[j] = max(sumOdd[j], sumEven[j]);
21                sumOdd[j] += nums[i];
22            }
23        }
24    }
25
26    for (int j = 0; j < 2; j++)
27    {
28        sumOdd[j] = max(sumOdd[j], sumEven[j]);
29    }
30    return max(sumOdd[0], sumOdd[1]);
31}

後記

2020大廠筆試 | 網易提早批(1)

2020大廠筆試 | 網易提早批(2)

揹包九講(1)0/1揹包問題

揹包九講(2)徹底揹包問題

數據結構類題目

  • LinkedList
  • 003-從尾到頭打印鏈表
  • 014-鏈表中倒數第k個結點
  • 015-反轉鏈表
  • 016-合併兩個或k個有序鏈表
  • 025-複雜鏈表的複製
  • 036-兩個鏈表的第一個公共結點
  • 055-鏈表中環的入口結點
  • 056-刪除鏈表中重複的結點
  • Tree
  • 004-重建二叉樹
  • 017-樹的子結構
  • 018-二叉樹的鏡像
  • 022-從上往下打印二叉樹
  • 023-二叉搜索樹的後序遍歷序列
  • 024-二叉樹中和爲某一值的路徑
  • 026-二叉搜索樹與雙向鏈表
  • 038-二叉樹的深度
  • 039-平衡二叉樹
  • 057-二叉樹的下一個結點
  • 058-對稱的二叉樹
  • 059-按之字形順序打印二叉樹
  • 060-把二叉樹打印成多行
  • 061-序列化二叉樹
  • 062-二叉搜索樹的第k個結點
  • Stack & Queue
  • 005-用兩個棧實現隊列
  • 020-包含min函數的棧
  • 021-棧的壓入、彈出序列
  • 044-翻轉單詞順序列(棧)
  • 064-滑動窗口的最大值(雙端隊列)
  • Heap
  • 029-最小的K個數
  • Hash Table
  • 034-第一個只出現一次的字符
  • 065-矩陣中的路徑(BFS)
  • 066-機器人的運動範圍(DFS)
  • 具體算法類題目
  • 斐波那契數列
  • 007-斐波拉契數列
  • 008-跳臺階
  • 009-變態跳臺階
  • 010-矩形覆蓋
  • 搜索算法
  • 001-二維數組查找
  • 006-旋轉數組的最小數字(二分查找)
  • 037-數字在排序數組中出現的次數(二分查找)
  • 全排列
  • 027-字符串的排列
  • 動態規劃
  • 030-連續子數組的最大和
  • 052-正則表達式匹配(我用的暴力)
  • 回溯
  • 065-矩陣中的路徑(BFS)
  • 066-機器人的運動範圍(DFS)
  • 排序
  • 035-數組中的逆序對(歸併排序)
  • 029-最小的K個數(堆排序)
  • 029-最小的K個數(快速排序)
  • 位運算
  • 011-二進制中1的個數
  • 012-數值的整數次方
  • 040-數組中只出現一次的數字
  • 其餘算法
  • 002-替換空格
  • 013-調整數組順序使奇數位於偶數前面
  • 028-數組中出現次數超過一半的數字
  • 031-整數中1出現的次數(從1到n整數中1出現的次數)
  • 032-把數組排成最小的數
  • 033-醜數
  • 041-和爲S的連續正數序列(滑動窗口思想)
  • 042-和爲S的兩個數字(雙指針思想)
  • 043-左旋轉字符串(矩陣翻轉)
  • 046-孩子們的遊戲-圓圈中最後剩下的數(約瑟夫環)
  • 051-構建乘積數組

劍指offer刷題交流羣

掃碼添加微信,必定要備註研究方向+地點+學校+暱稱(如機器學習+上海+上交+湯姆),只有備註正確才能夠加羣噢。

Leetcode (213)| 打家劫舍 2
▲長按加羣

Leetcode (213)| 打家劫舍 2

相關文章
相關標籤/搜索