1. 程式人生 > >Leetcode 075 顏色分類 Python C++ 史上最詳細題解系列(多解法)

Leetcode 075 顏色分類 Python C++ 史上最詳細題解系列(多解法)


每天更新一道python or C++ leetcode題,力求講解清晰準確,客官們可以點贊或者關注。

題目:

給定一個包含紅色、白色和藍色,一共 個元素的陣列,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。

此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。

注意:
不能使用程式碼庫中的排序函式來解決這道題。

示例:

輸入: [2,0,2,1,1,0]
輸出: [0,0,1,1,2,2]

進階:

  • 一個直觀的解決方案是使用計數排序的兩趟掃描演算法。
    首先,迭代計算出0、1 和 2 元素的個數,然後按照0、1、2的排序,重寫當前陣列。
  • 你能想出一個僅使用常數空間的一趟掃描演算法嗎?

首先給出直觀的解決方案,也就是進階裡已經寫出來了的。

class Solution:
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        num0 = 0
        num1 = 0
        num2 = 0
        i = 0
        while i < len(nums):
            if nums[i] == 0:
                num0 += 1
            elif nums[i] == 1:
                num1 += 1
            elif nums[i] == 2:
                num2 += 1
            i += 1
        j = 0
        while j < len(nums):
            if num0 > 0:
                nums[j] = 0
                num0 -= 1
            elif num1 > 0:
                nums[j] = 1
                num1 -= 1
            elif num2 > 0:
                nums[j] = 2
                num2 -= 1
            j += 1
        

這個演算法的話可以說基本練過leetcode的人都能寫得出。

接下來介紹進階的做法:三向切分。

首先直觀地從名字上去理解演算法。

這個演算法的目的是使的陣列分成3個區間,每個區間的元素是相同的,而且這3個區間按大小排序。

好,知道了演算法的目的,怎麼實現呢?

演算法過程:

1.初始化2個指標,一個指向陣列的開頭-1,一個指向結尾+1

2.zero_end是指的是0的區間的邊界所在的index,two_begin是2的區間的邊界所開始的index.

3.遇到一個0,我們把那個0和nums[++zero_end]交換,注意這個時候zero_end加1了,同時如果是2,也就是最後一個區間的元素,我們需要與two_begin上所在的元素交換,同時two_begin也減去了1,如果是1,也就是中間區間的元素,則跳過。

class Solution
{
	public:
		// 交換兩個數函式 
		void swap(int &a, int &b)
		{
			int temp = a;
			a = b;
			b  = temp;
		} 
		void sortColors(vector<int> &nums)
		{
			int zero_end = -1;
			int two_begin = nums.size();
			int i = 0;
			while (i < two_begin)
			{
				if (nums[i] == 0 && i != ++zero_end)
				{
					swap(nums[i], nums[zero_end]);
				}
				else if (nums[i] == 2 && i != --two_begin)
				{
					swap(nums[i], nums[two_begin]);
				}
				else
					i++;
			} 
		}
};

可能很多人不知道為什麼這樣能夠排序,我這裡稍微講個例子:

[1,...0,...]假設有這麼一個數組,第一位是1,第k位出現了第一個0,根據我們的演算法,我們會跳過1,然後當我們遇到第一個0的時候,我們會把1和0交換,也就是說變成[0,...1,...],這時候i位變成1了,繼續跳過,所以我們的指標能不斷前進。

更強更簡潔的程式碼:

接下來要介紹的演算法,已經超神了。它不是那麼好理解,但它又有三向切分的影子。、

讀程式碼前一定要搞懂:

1.i,j, k 分別指向當前遍歷的陣列的最後一個0,1,2的位置。

比如,當前已處理好的部分陣列是 0 0 0 0 1 1 1 2 2 2 *,那麼i,j,k分別指向最後一個0,1,2。m指向*,*號為待處理元素,

 2.++k的結果是k+1

3.如果i,j,k一樣,則它們對應的賦值則有可能覆蓋對方的賦值。

4.如果沒懂,多讀幾遍

所以我們的演算法就是,

遇到0,1,2把i,j,k後面1位的值賦成對應的值即可。

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int i = -1,j = -1,k = -1;//注意i,j,k的含義
        int m;
        for(m = 0; m < nums.size();m++){
            if(nums[m] == 0){
                nums[++k] = 2;
                nums[++j] = 1;
                nums[++i] = 0;
            }
            else if(nums[m] == 1){
                nums[++k] = 2;
                nums[++j] = 1;
            }
            else {
                nums[++k] = 2;
            }
        }
    }
};

總結:

學習了三向切分的2種實現形式,

一種是常規的設定各區間邊界的解法:

1.先設定第一個區間的末尾邊界,再設定第三個區間的開頭邊界。

2.遇到第一區間的元素(0),與第一區間末尾邊界交換,末尾邊界+1;遇到第2區間的元素,跳過;遇到第三區間的元素,與第三區間開頭邊界交換,並加1。

一種是設定三個指標的三向切分:

i指向第一小元素的最後一個index,j指向第2小元素的最後一個index, k指向第三小元素的最後一個index。

遇到第一小的元素,把i,j,k都往後推一步,並且在賦值。

遇到第2小的元素,由於只會影響2,3區間,於是只用把,j,k往後推一步再賦值。

遇到第3小的元素,只會影響3區間,把k往後推一步賦值。

1區間指第一個區間,也就是最小的區間。

今天總結乾貨很多,但同時也發現了自己的基礎不牢,因為三向切分在《演算法》4中講過,忘乾淨了。。

相關推薦

Leetcode 075 顏色分類 Python C++ 詳細題解系列解法

每天更新一道python or C++ leetcode題,力求講解清晰準確,客官們可以點贊或者關注。 題目: 給定一個包含紅色、白色和藍色,一共 n 個元素的陣列,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。 此題中,我們使用整數

Leetcode 079 搜尋單詞 Python C++ 詳細題解系列

題目: 給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。 單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重複使用。 示例: board = [ ['A','B','C',

Leetcode 81 搜尋旋轉排序陣列 II Python C++ 詳細題解系列

題目: 假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。 ( 例如,陣列 [0,0,1,2,2,5,6] 可能變為 [2,5,6,0,0,1,2] )。 編寫一個函式來判斷給定的目標值是否存在於陣列中。若存在返回 true,否則返回 false。 示例 1:

利用Python實現導彈自動追蹤!室友面前的裝逼利器!詳細

技術 取數 跟隨鼠標 構造 制作 思想 室友 相同 精確 不好意思 ,上傳錯了。接著看圖! 由於待會要用pygame演示,他的坐標系是y軸向下,所以這裏我們也用y向下的坐標系。 算法總的思想就是根據上圖,把時間t分割成足夠小的片段(比如1/1000,

詳細的爬蟲教程,Python採集全網受歡迎的 500 本書!

      想看好書?想知道哪些書比較多人推薦,最好的方式就是看資料,接下來用 Python 爬取噹噹網五星圖書榜 TOP500 的書籍,或許能給我們參考參考! Python爬取目標   爬取噹噹網前500本受歡迎的書籍 解析書籍名稱

詳細完全的ipython使用教程,Python使用者必備!——ipython系列之二

宣告:本文承接前面一篇文章,ipython系列之一;另外,本文所指的ipython不是ipython notebook,ipython notebook已經被jupyter notebook所取代,不再叫ipython notebook了。 前面講解了ipython裡面的一些核心

詳細完全的ipython使用教程,Python使用者必備!——ipython系列之一

一、ipython簡介 關於什麼是ipython,本文就不加以介紹了,他是一個非常流行的python直譯器,相比於原生的python直譯器,有太多優點和長處,因此幾乎是python開發人員的必知必會。 1、ipython相比於原生的python有什麼優勢 (1) pyth

C++ 華而不實的類

下面大家要看到這個類完全是扯淡,一無是處。它是由感而發於帖子C++的二維陣列轉置。 當時,看完帖子我就在想,能不能用過載的方式實現邏輯轉置?只是好奇。C++顯然是不能過載兩個 [][] ,但是要達到這個效果,只要讓 [] 操作符返回一個指標即可。 問題是這樣根本做不到一個邏

python小課堂專欄】python小課堂15 - 詳細的包和模組import講解篇

python小課堂15 - 史上最詳細的包和模組import講解篇 前言 在大量的程式碼設計中,我們不可能將所有程式碼都寫在一個.py檔案,所以有了包、模組,而為了程式碼可以重複利用(複用性),就有了類、函式的概念。類和函式在下次介紹。 python中的包 python中

python小課堂專欄】python小課堂14 - 詳細安裝破解PyCharm篇

python小課堂14 - 程式碼編輯器PyCharm篇 前言 古人云:工欲善其事必先利其器!寫程式碼也一樣,雖然好多人都說,初學者不推薦使用很高大上,智慧,自動化的編輯器,但是我想說:“強大的,智慧的東西為什麼就不推薦新手用呢?!!”我自學java的時候,也直接用的是eclip

詳細Python爬取電影教程,還不會那也是沒誰了

摘要: 作為小白,爬蟲可以說是入門python最快和最容易獲得成就感的途徑。因為初級爬蟲的套路相對固定,常見的方法只有幾種,比較好上手。選取網頁結構較為簡單的貓眼top100電影為案例進行練習。 重點是用上述所說的4種方法提取出關鍵內容。一個問題採用不同的解決方法有助於拓展思維,通過不斷練

詳細c語言學生管理系統完整的原始碼

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> struct student { char sno[12]; char n

詳細完全的jupyter notebook使用教程,Python使用者必備!——ipython系列之三

一、什麼是jupyter 1、簡介: jupyter notebook是一種 Web 應用,能讓使用者將說明文字、數學方程、程式碼和視覺化內容全部組合到一個易於共享的文件中。它可以直接在程式碼旁寫出敘述性文件,而不是另外編寫單獨的文件。也就是它可以能將程式碼、文件

Python爬蟲入門到實戰-詳細的爬蟲教程

技術分享 圖片 color blog .com 教程 robot http 進階 馬哥高薪實戰學員 【Python爬蟲入門到實戰-史上最詳細的爬蟲教程,限時免費領取】 爬蟲分類和ROBOTS協議 爬蟲URLLIB使用和進階 爬蟲URL編碼和GETPOST請求 Python爬

詳細Windows版本搭建安裝React Native環境配置

gin windows系統 adl 搭建環境 tools 想要 變量 rep home 說在前面的話: 感謝同事金曉冰傾情奉獻本環境搭建教程 之前我們已經講解了React Native的OS X系統的環境搭建以及配置,鑒於各大群裏有很多人反應在Windows環境搭建出現各種

移植QT5.6到嵌入式開發板詳細的QT移植教程

文件傳輸 嵌入式環境 ubun 導致 字庫 etc -a led fill 目前網上的大多數 QT 移植教程還都停留在 qt4.8 版本,或者還有更老的 Qtopia ,但是目前 Qt 已經發展到最新的 5.7 版本了,我個人也已經使用了很長一段時間的 qt5.6 for

詳細nodejs版本管理器nvm的安裝與使用附註意事項和優化方案

技術 註意 nod core 遇到 target 快速 方式 get 使用場景 在Node版本快速更新叠代的今天,新老項目使用的node版本號可能已經不相同了,node版本更新越來越快,項目越做越多,node切換版本號的需求越來越迫切,傳統卸載一個版本在安裝另一個版本的方

Android Studio獲取開發版SHA1值和發布版SHA1值的詳細方法

nal code tail JD rip 通過 提示 打開 tor 前言:使用百度地圖時需要秘鑰,申請秘鑰時需要SHA1值,所以今天就總結一下怎麽獲取這個值。 正常情況下: 一、獲取開發版SHA1: 在此我直接用AndroidStudio提供的命令控制臺了,畢竟做Andro

XX-NET詳細完整教程

偽造 不用 app 分享圖片 AS 版本 firefox 配置過程 自動切換 前言   XX-NET,系GAE類代理,即通過可用Google ip連接Google App Engine項目,然後把所有tcp請求發送給Google App Engine,最終實現科學式網絡的

簡單的springboot國際化語言切換實現方案

messages conf main del span 語言 rop target 每天 每天學習一點點 編程PDF電子書、視頻教程免費下載:http://www.shitanlife.com/code 前提: 在resources目錄下建立 messages_en