We have two special characters. The first character can be represented by one bit 0. The second character can be represented by two bits (10 or 11).
Now given a string represented by several bits. Return whether the last character must be a one-bit character or not. The given string will always end with a zero.
Example 1:
Input: bits = [1, 0, 0] Output: True Explanation: The only way to decode it is two-bit character and one-bit character. So the last character is one-bit character.
Example 2:
Input: bits = [1, 1, 1, 0] Output: False Explanation: The only way to decode it is two-bit character and two-bit character. So the last character is NOT one-bit character.
Note:
1 <= len(bits) <= 1000.bits[i]is always0or1.
這道題說有兩種特殊的字符,一種是兩位字符,只能是二進制的11和10,另一種是單個位字符,只能是二進制的0。現在給了我們一個只包含0和1的數組,問我們能否將其正確的分割,使得最后一個字符是個單個位字符。這道題可以使用貪婪算法來做,因為兩種字符互不干擾,只要我們遍歷到了數字1,那么其必定是兩位字符,所以后面一位也得跟着,而遍歷到了數字0,那么就必定是單個位字符。所以我們可以用一個變量i來記錄當前遍歷到的位置,如果遇到了0,那么i自增1,如果遇到了1,那么i自增2,我們循環的條件是i < n-1,即留出最后一位,所以當循環退出后,當i正好停留在n-1上,說明最后一位是單獨分割開的,因為題目中限定了最后一位一定是0,所以沒必要再判斷了,參見代碼如下:
解法一:
class Solution { public: bool isOneBitCharacter(vector<int>& bits) { int n = bits.size(), i = 0; while (i < n - 1) { if (bits[i] == 0) ++i; else i+= 2; } return i == n - 1; } };
下面這種解法寫的更加簡潔了,直接用一行代替了if..else..語句,相當巧妙,當bits[i]為0時,i還是相當於自增了1,當bits[i]為1時,i相當於自增了2,最后還是在循環跳出后檢測i是否為n-1,參見代碼如下:
解法二:
class Solution { public: bool isOneBitCharacter(vector<int>& bits) { int n = bits.size(), i = 0; while (i < n - 1) { i += bits[i] + 1; } return i == n - 1; } };
下面我們來看遞歸解法,用的是回溯的思想,首先判斷如果bits為空了,直接返回false,因為題目初始給的bits是非空的,在調用遞歸函數中為空了說明最后一位跟倒數第二位組成了個兩位字符,所以不合題意返回false。再判斷如果bits大小為1了,那么返回這個數字是否為0,其實直接返回true也行,因為題目中說了最后一個數字一定是0。然后我們新建一個數組t,如果bits的首元素為0,則我們的t賦值為去掉首元素的bits數組;如果bits的首元素是1,則我們的t服之為去掉前兩個元素的bits數組,然后返回調用遞歸函數的結果即可,參見代碼如下:
解法三:
class Solution { public: bool isOneBitCharacter(vector<int>& bits) { if (bits.empty()) return false; if (bits.size() == 1) return bits[0] == 0; vector<int> t; if (bits[0] == 0) { t = vector<int>(bits.begin() + 1, bits.end()); } else if (bits[0] == 1) { t = vector<int>(bits.begin() + 2, bits.end()); } return isOneBitCharacter(t); } };
下面這種解法也是用的遞歸,遞歸函數用的不是原函數,這樣可以只用位置變量idx來遍歷,而不用新建數組t,初始時idx傳入0,在遞歸函數中,如果idx為n了,相當於上面解法中的bits數組為空了情況,返回false;如果idx為n-1,返回true;如果bits[idx]為0,則返回調用遞歸函數的結果,此時idx加上1;如果bits[idx]為1,則返回調用遞歸函數的結果,此時idx加上2,參見代碼如下:
解法四:
class Solution { public: bool isOneBitCharacter(vector<int>& bits) { return helper(bits, 0); } bool helper(vector<int>& bits, int idx) { int n = bits.size(); if (idx == n) return false; if (idx == n - 1) return bits[idx] == 0; if (bits[idx] == 0) return helper(bits, idx + 1); return helper(bits, idx + 2); } };
類似題目:
參考資料:
https://discuss.leetcode.com/topic/108743/java-solution-1-or-2
https://discuss.leetcode.com/topic/108766/c-both-iterative-and-recursive-solutions
