array专题5
#561 Array Partition I#
思路:題目要求數組中所有數字配對后,每一對中最小值加和sum,sum要盡可能大。我的第一反應就是暴力枚舉。下標為0的數值可能匹配的下標有:1,2,3…n-1;接著計算下標為1的數值可能匹配的下標有哪些。不斷匹配,直到數組中所有數字配對完成。求和,保存和最大的值。可以得出結果,時間復雜度O(n^n)。n的n次冪。因為有n步,每步有n種情況。
學習:先排序數組,然后相鄰的做paire。原因是這樣的。如果一個數組已經排序好,則有a0,a1,a2…a(2n-1)。所求和最大的應該是a0+a2+…a+(2n-2) ,這是因為(a0,a1),(a2,a3)…;最小的和是 a0+a1+a2+…+a(n-1),這是因為(a0,an),(a1,a(n+1))這樣匹配。還有另外一種解釋。要想讓和最大,則需要每個數值盡可能大。觀察:如果一次配對,當 (1,4) 與 (1,2)比較的時候就會發現(1,2)pair 要比(1,4)pair 要好。因為4這個數字可能與其他數字配對被保留下來。而(1,4)配對,那4一定被舍棄。所以,能夠看出配對的兩個數字要盡可能接近。這里的時間復雜度主要是排序的時間復雜度O(nlogn)。
學習2:上面的主要時間耗在排序,其實排序還有一種思路是桶排序。就是把相同的數字放在一個桶里面。在配對的時候還是把盡可能相同的數字放在一起配對。
參考:網頁1;網頁2;網頁3
我學習到的就是做題目除了依賴直覺,還需要靠觀察。從觀察中總結規律,進而提高算法效率。
代碼
#566 Reshape the Matrix
思路:這道題是一道真正的easy級別,按照題目描述直接寫代碼即可。
學習:這里學習到的一點是對下標的巧妙利用。當然,這不影響算法的時間復雜度。二維數組變一維數組 M[i][j]=M[i*n+j],n是列數;一維變二維 M[i] = M[i/n][i%n],n是列數;
#775 Global and Local Inversions
思路:按照題目要求,分別計算全局反轉次數與局部反轉次數。這樣會產生O(n^2)的時間復雜度。
學習:題目中提到了一個很重要的信息,We have some permutation A of [0, 1, …, N - 1], where N is the length of A。這說明正常的A=[0,1,2,3,…N-1],也就是說A[i] = i , 0<=i<N0<=i<N0<=i<N。
進一步分析得到:
1 每個local inversion 也是一個global inversion
2 如果想要 localCount = globalCount,也就是說只有local inversion,沒有其余的global inversion
3 如果只有local inversion,那么當遇到inversion的時候,只要交換A[i]和A[i+1]的位置,那么數組從0到i+1就有序了。
例如A = [1,0,2]。當i=1的時候,A[1]<A[0]A[1]<A[0]A[1]<A[0],那么交換A[1]和A[0]之后,A=[0,1,2],那么A[0]=0,A[1]=1,符合A[i] = i的要求。那這數組從0到1是有序的,這是一次local inversion。
例如A = [2,0,1]。當i=1的時候,A[1]<A[0]A[1]<A[0]A[1]<A[0],那么交換A[1]和A[0]之后,A=[0,2,1],那么A[0]=0,A[1]=2,A[1]不符合A[1]=1的要求。那這樣就可以立即返回false。
代碼
#495 Teemo Attacking
思路: 根據題目含義,這是要處理重復線段的問題。 例如[1,2], 2;第一次起始時間是1,結束時間是3(或者2s的末尾);第二次起始時間是2,結束時間是4(或者3s的末尾)。 用第一次的結束時間-第二次的起始時間,就是重復的時間。
代碼
#62 Unique Paths
思路:在每個位置(i,j)有兩種走向:向右走到達(i+1,j),向下走到達(i,j+1)。暴力搜索每種情況。處理邊界條件。這樣會超時。
思路二:動態規劃思想:dp[i][j]表示到達(i,j)位置,有幾種走法。初始條件是第一行、第一列的每個位置只有一種走法所以dp[0][] = 1,dp[][0]=1;遞歸條件 dp[i][j] = dp[i-1][j]+dp[i][j-1]。時間復雜度O(m*n)
學習:排列組合思想:表格是m行,n列,robot需要向下移動m-1次,向右移動n-1次。如果用D表示向下,R表示向右。例如在3x7的表格中,需要2次D,6次R。這樣可以是任意組合例如D,D,R,R,R,R,R,R或者D,R,D,R,R,R,R,R。這樣只需要計算(m-1)+(n-1)的組合數。
代碼
#442 Find All Duplicates in an Array
思路:題目要求不用額外的空間,在O(n)時間內完成,這樣就要非常注重一個前提1 ≤ a[i] ≤ n (n = size of array),數組內的元素是在長度范圍內的。這樣就可以將數組的下標與數組的值建立映射關系。這里建立映射的關系是把nums[i]放在nums[i]-1 的位置上。如果nums[nums[i]-1]已經等于nums[i]了,那說明是重復的。(nums[i] = -1 就說明是缺失的值)
學習:不用交換數值,只需要將對應位置修改為負數即可。
代碼
#63 Unique Paths II
思路:與62類似,用動態規劃解決。注意條件判斷即可。
問題:沒有找到更快的方法。
代碼
287 Find the Duplicate Number
學習思路一:Floyd龜兔法
學習思路二:二分法
代碼
15 3Sum
思路:三個數相加和為0,轉為固定一個數nums[i],求兩個數的和為0-nums[i]。將nums排序后,用兩個指針從最前面和最末尾開始移動。
代碼
18 4Sum
思路:可以基于3Sum,將一個數固定nums[i],再剩余數組中查找三個數和為target-nums[i]。三個數的和再轉為2個數的和。
思路2:可以使用map,將兩兩數的和存起來放在map中,再循環nums,得到兩個下標。這樣做的最大難題是去重。參考discuss的代碼
代碼
#73 Set Matrix Zeroes
思路:看起來比較簡單的一道題。難點是注意修改和判斷不能相互影響。例如matrix[2][3]=0,則matrix[2][]=0,matrix[][3] = 0。那么在判斷第三行的時候,只能依據修改前的matrix[3][3]來判斷是為0,而不能依據修改后的。我的思路是先遍歷一遍找,分別找到需要置0的行和列,放入list中。然后再遍歷這些行,每一列設置為0;遍歷這些列,每一行的該列設置為0。
學習1:遍歷如果某一行包含元素0,則修改matrix[i][0] =0;如果某一列包含元素0,則修改matrix[0][j]=0;但是第0行和第0列會共享同一個空間matrix[0][0],則需要添加一個變量col0,col0=0表示第0列為0;matrix[0][0]=0則表示第0行為0。
代碼
總結
- 上一篇: 【翻译】Adaptive Convolu
- 下一篇: 五大常用算法汇总