LeetCode進階944-算法優化

概要

本篇經過944題演示實際學習過程當中正確的解題思路,以及學習方法。算法相關的程序設計力求完美,在系統環境支持的狀況下,時間和空間複雜度的考慮是首要因素,實際項目中針對算法相關的業務不妨多考慮一步,正所謂失之毫釐,差之千里!作到精益求精,總歸是有幫助的。本篇題解思路相對簡單,重在分析針對同一思路,對細節進行優化提升算法效率。java

原題

944. Delete Columns to Make Sorted

We are given an array A of N lowercase letter strings, all of the same length.算法

Now, we may choose any set of deletion indices, and for each string, we delete all the characters in those indices.數組

For example, if we have an array A = ["abcdef","uvwxyz"] and deletion indices {0, 2, 3}, then the final array after deletions is ["bef", "vyz"], and the remaining columns of A are ["b","v"], ["e","y"], and ["f","z"]. (Formally, the c-th column is [A[0][c], A[1][c], ..., A[A.length-1][c]].)微信

Suppose we chose a set of deletion indices D such that after deletions, each remaining column in A is in non-decreasing sorted order.學習

Return the minimum possible value of D.length.優化

Example 1:spa

Input: ["cba","daf","ghi"] Output: 1 Explanation: After choosing D = {1}, each column ["c","d","g"] and ["a","f","i"] are in non-decreasing sorted order. If we chose D = {}, then a column ["b","a","h"] would not be in non-decreasing sorted order. Example 2:設計

Input: ["a","b"] Output: 0 Explanation: D = {} Example 3:code

Input: ["zyx","wvu","tsr"] Output: 3 Explanation: D = {0, 1, 2}orm

Note:

1 <= A.length <= 100 1 <= A[i].length <= 1000

944. 刪除非排序列(根據題意命名)

一個大小爲N數組A,數組的每一個元素是都是小寫字母組成的字符串,其中每一個字符串長度相等。

刪除操做:刪除一列,從A中刪除這一列的全部字符,好比,第 n 列爲 [A[0][n], A[1][n], ..., A[A.length-1][n]])。

加入有一個數組A = ["abcdef", "uvwxyz"],

被刪除的列爲 {0, 2, 3},刪除後A成爲["bef", "vyz"], 刪除後A的列分別是["b","v"], ["e","y"], ["f","z"]。

請選出一組要刪掉的列D,對A執行刪除操做,A剩餘的每一列都是非降序排列的,最後返回D.length的最小值。

例 1:

輸入:["cba", "daf", "ghi"] 輸出:1 說明: 選擇 D = {1},刪除後 A 的列爲:["c","d","g"] 和 ["a","f","i"],爲非降序排列。 若選擇 D = {}(不刪除),那麼 A 的列 ["b","a","h"] 不是非降序排列

例 2:

輸入:["a", "b"] 輸出:0 說明:D = {} (無需刪除)

例 3:

輸入:["zyx", "wvu", "tsr"] 輸出:3 說明:D = {0, 1, 2}

提示:

1 <= A.length <= 100 1 <= A[i].length <= 1000

  • 本題在LeetCode上屬於貪心算法分類下

題意分析

本題所屬分類雖在貪心算法下,可是顯然屬於統計數組中須要刪除的非升序排列的列數,天然容易聯想到最簡單的方式,直接循環統計的方式。

思路:

循環統計法,循環遍歷每一列,遍歷當前列的某個元素時,對比當前字符和當前列的上一個字符是否爲非降序,若爲非降序列,則計數加1,遍歷完成後得出總的非升序總列數。

僞代碼

1、聲明一個計數變量count;
2、根據列數進行for循環遍歷
3、循環中再針對當前列進行比較統計,若當前列當前元素和上一元素對比爲非升序排列,則計數加1
複製代碼

普通版:

public int minDeletionSize1(String[] A) {
		if (A.length == 0) return 0;
		int count = 0;
		for (int i = 0; i < A[0].length(); i++) {
			for (int j = 1; j < A.length; j++) {
				if (A[j].charAt(i) < A[j - 1].charAt(i)) {
					count++;
					break;
				}
			}
		}
		return count;
	}
複製代碼
  • 普通版執行結果:
    普通版執行結果

進階版

public int minDeletionSize(String[] A) {
		if (A == null) return 0;
		int count = 0;
		for (int i = 0; i < A[0].length(); ++i) {
			if(isNoSort(A, i)) ++count;
		}
		return count;
	}
	
	public static boolean isNoSort(String[] A, int num) {
		for (int i = 1; i < A.length; ++i) {
			if (A[i].charAt(num) < A[i-1].charAt(num)) return true;
		}
		return false;
	}
	
複製代碼
  • 進階版執行結果:
    進階版執行結果

終極版

public int minDeletionSize(String[] A) {
		if (A == null) return 0;
		int count = 0;
       int len = A[0].length();
		for (int i = 0; i < len; i++) {
			if(isNoSort(A, i)) count++;
		}
		return count;
	}
    
	public static boolean isNoSort(String[] A, int num) {
		char c = A[0].charAt(num);
		for (int i = 0; i < A.length;i++) {
			if (A[i].charAt(num) < c) return true;
			c = A[i].charAt(num);
		}
		return false;
	}
複製代碼
  • 終極版執行結果:
    終極版執行結果

優化說明

能夠看到通過優化後的算法,執行速度從擊敗64.42%到99.67%再到100%,有一個質的飛躍。重點是這三種方法的核心算法思想都同樣,只是略有細節上的區別。

  • 進階版對比普通版

明顯可見的區別是,將內存循環遍歷判斷是否有非升序的邏輯封裝成了一個單獨的方法,核心邏輯沒有任何變化

  • 終極版對比進階版

觀察細節不難發現有兩處明顯的變化:

1.外層循環長度變量從放在for循環內部變成變量len移動到循環外部,避免每次for循環都會重複調用length()方法。

2.排序方法isNoSort裏對比邏輯if條件,由兩個元素分別調用charAt方法,變成一個元素調用charAt方法,前一個元素的具體char數值由一個臨時變量存儲,每次循環的時候賦值,這樣節省了在循環內部調用charAt方法的開銷。

彩蛋

進階版對比普通版效率上有質的提升,主要是將雙重for循環的內存循環拆成了獨立的方法,這即是本文的彩蛋,感興趣能夠關注一波博主的微信訂閱號,後續會針對文中彩蛋做統一解答^_^

Alt

掃一掃 關注個人微信訂閱號
相關文章
相關標籤/搜索