問題描述
把數列中每個元素左邊小於自身的元素加起來
如:
{1, 2, 3},2的左邊只有1小於,3左邊有1和2小於,加起來的小和值就是4
{1,3,5,0,2,4}1 3 5 | 0 2 41 3|5 0 2|41|3 0|2
這個其實是練習歸併排序
已知歸併過程如下: 首先劃分劃分劃分,一直劃分到不能劃分,即每個組都只有一個數值。 然後合并,合并的過程就是每個二劃分排序的過程。 在合并的時候,開闢一個輔助數組,其大小等於這兩個合并數列的大小。 設定兩個指標分別指向每個數列的首部,然後比較得到其中較小的值,並將這個值放入輔助數組中。然後取出小值的那個數列的指標可以繼續向前走,與另一個數列的指標所指向的值繼續比較 這樣比較完成後,如果兩個數列中有個數列的數值有剩餘,即其指標沒有走到末尾,則將這個數列直接賦到輔助數組末尾即可。 然後將輔助數組中的值拷貝回原數組中剛才合并的那兩個數列的位置上。
其實就是在每次歸併排序的時候計算小於的和
count += a[p1] < a[p2] ? (r - p2 + 1)*a[p1] : 0;
java:
import java.io.*;class test { public static int smallSum(int[] arr) { if (arr == null || arr.length < 2) { return 0; } return mergeSort(arr, 0, arr.length - 1); } public static int mergeSort(int[] arr, int l, int r) { if (l == r) { return 0; } int mid = l + ((r - l) >> 1); return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r); } public static int merge(int[] arr, int l, int m, int r) { int[] help = new int[r - l + 1]; int i = 0; int p1 = l; int p2 = m + 1; int res = 0; while (p1 <= m && p2 <= r) { res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0; help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; } while (p1 <= m) { help[i++] = arr[p1++]; } while (p2 <= r) { help[i++] = arr[p2++]; } for (i = 0; i < help.length; i++) { arr[l + i] = help[i]; } return res; } public static void main (String[] args) throws java.lang.Exception { int[] arr = { 1,2,3}; System.out.println(smallSum(arr)); }}
python:
#!/usr/bin/python# -*- coding: utf-8 -*-def small_sum(arr): if not arr or len(arr)<1: return 0 return merge_sort(arr, 0, len(arr) - 1)def merge_sort(arr, l, r): if l == r : return 0 mid = l + ((r - l) >> 1) return merge_sort(arr, l, mid) + merge_sort(arr, mid + 1, r) + merge(arr, l, mid, r)def merge(arr, l, m, r): help = [] p1 = l p2 = m + 1 res = 0 while p1 <= m and p2 <= r : res += (r - p2 + 1) * arr[p1] if arr[p1] < arr[p2] else 0 if arr[p1] < arr[p2] : help.append(arr[p1]) p1 += 1 else : help.append(arr[p2]) p2 += 1 while p1 <= m : help.append(arr[p1]) p1 += 1 while p2 <= r : help.append(arr[p2]) p2 += 1 for i in range(len(help)): arr[l + i] = help[i] return res;from array import arrayarr = array('b', (1, 2, 3))print(small_sum(arr))
添加一個python版本是為了從之前的c/c++、java中的文法操作轉換過了,當然我對這代碼還是很不滿意的。之前學習了那麼久的python,以為自己掌握了文法,但真正轉換的時候還是挺碰壁的,有些不同的變化之前知道,但容易忘記還得查資料,python版本的代碼還想追求更pythonic,以後會不斷修改的。
希望各位博友能夠對python代碼提出更優雅格式的指點讓我學習,感謝。
來源資料:
牛客網左神演算法視頻:
https://www.nowcoder.com/
歸併過程來之該博友的總結:
https://blog.csdn.net/liuxiao214/article/details/78530993