Algorithm Sort

记录 Sort 的算法实现

“164. Maximum Gap”

// Radix sort
func maximumGap(nums []int) (ret int) {
    n := len(nums)
    if n < 2 {
        return 0
    }
    maxVal := max(nums...)
    buf := make([]int, n)
    for exp := 1; exp <= maxVal; exp *= 10 {
        count := make([]int, 10)
        for _, num := range nums {
            digit := num / exp % 10
            count[digit]++
        }
        for i := 1; i < len(count); i++ {
            count[i] += count[i-1]
        }
        for i := n-1; i >= 0; i-- {
            digit := nums[i] / exp % 10
            buf[count[digit]-1] = nums[i]
            count[digit]--
        }
        copy(nums, buf)
    }

    for i := 1; i < n; i++ {
        ret = max(ret, nums[i]-nums[i-1])
    }
    return ret
}
// Bucket sort
func maximumGap(nums []int) (ret int) {
    n := len(nums)
    if n < 2 {
        return 0
    }

    minVal, maxVal := min(nums...), max(nums...)
    d := max(1, (maxVal-minVal)/(n-1))  // min distance
    bucketSize := (maxVal-minVal)/d+1
    b := make([][2]int, bucketSize)
    for i := range b {
        b[i] = [2]int{-1,-1}    // min, max
    }
    for _, num := range nums {
        idx := (num-minVal)/d
        if b[idx][0] == -1 {
            b[idx] = [2]int{num, num}
        } else {
            b[idx][0] = min(b[idx][0], num)
            b[idx][1] = max(b[idx][1], num)
        }
    }

    for l,i := 0,1; i < len(b); i++ {
        if b[i][0] == -1 {
            continue
        }
        ret = max(ret, b[i][0]-b[l][1])
        l = i
    }
    return ret
}

“215. Kth Largest Element in an Array”

// quick sort
func findKthLargest(nums []int, k int) int {
    sort.Sort(sort.Reverse(sort.IntSlice(nums)))
    return nums[k-1]
}
// nth_element
func findKthLargest(nums []int, k int) int {
    rand.Seed(time.Now().UnixNano())
    l, r, tar := 0, len(nums)-1, len(nums)-k
    for {
        index := partition(nums, l, r)
        if index == tar {
            return nums[index]
        } else if index > tar {
            r = index - 1
        } else {
            l = index + 1
        }
    }
    return -1
}

func partition(nums []int, l, r int) (ret int) {
    x := rand.Intn(r-l+1) + l   // 随机取 pivot 优化,nums[r] == pivot
    nums[x], nums[r] = nums[r], nums[x]
    for i := l; i < r; i++ {
        if nums[i] <= nums[r] {
           nums[l], nums[i] = nums[i], nums[l]
           l++
        }
    }
    nums[l], nums[r] = nums[r], nums[l]
    return l
}

“274. H-Index”

// Count sort
func hIndex(citations []int) (h int) {
    n := len(citations)
    counter := make([]int, n+1)
    for _, citation := range citations {
        if citation >= n {
            counter[n]++
        } else {
            counter[citation]++
        }
    }
    for i, tot := n, 0; i >= 0; i-- {
        tot += counter[i]
        if tot >= i {
            return i
        }
    }
    return 0
}

“324. Wiggle Sort II”

int n = nums.size();
// Find a median.
auto midptr = nums.begin() + n / 2;
nth_element(nums.begin(), midptr, nums.end());
int mid = *midptr;
// Index-rewiring.
#define A(i) nums[(1+2*(i)) % (n|1)]
// 3-way-partition-to-wiggly in O(n) time with O(1) space.
int i = 0, j = 0, k = n - 1;
while (j <= k) {
    if (A(j) > mid)
        swap(A(i++), A(j++));
    else if (A(j) < mid)
        swap(A(j), A(k--));
    else
        j++;
}

“645. Set Mismatch”

func findErrorNums(nums []int) (ret []int) {
    for i := 0; i < len(nums); i++ {
        for nums[i] != 0 && nums[i]-1 != i {
            if nums[nums[i]-1] == nums[i] {
                ret = append(ret, nums[i])
                nums[i] = 0
                break
            }
            nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]
        }
    }

    for i, v := range nums {
        if v == 0 {
            ret = append(ret, i+1)
            break
        }
    }

    return ret
}

“912. Sort an Array” QuickSort C++

// 三数取中法优化函数,效果较好
template<typename T1>
    void selectPivotOfThree(vector<T1> &nums, int lo, int hi) {
        int m = (lo + hi) >> 1;
        if (nums[m] > nums[hi])
            swap(nums[m], nums[hi]);
        if (nums[lo] > nums[hi])
            swap(nums[lo], nums[hi]);
        if (nums[m] > nums[lo])
            swap(nums[lo], nums[m]);
    }

    // 随机取数法,
    template<typename T1>
    void selectPivotByRand(vector<T1> &nums, int lo, int hi) {
        int idx = lo + (rand() % (hi - lo + 1));
        swap(nums[lo], nums[idx]);
    }

    template<typename T1>
    void quickSort(vector<T1> &nums, int lo, int hi) {
        if (lo >= hi) return;  // 注意这里要及时退出
        //selectPivotOfThree<T1>(nums, lo, hi);
        selectPivotByRand(nums, lo, hi);
        T1 pivot = nums[lo];
        int l = lo, r = hi;
        while (l < r) {
            while (l < r && nums[r] >= pivot)
                r--;
            swap(nums[l], nums[r]);
            while (l < r && nums[l] <= pivot)
                l++;
            swap(nums[l], nums[r]);
        }
        quickSort(nums, lo, l);   // 注意这里不能是l-1
        quickSort(nums, l + 1, hi);
    }
	vector<int> sortArray(vector<int>& nums) {
		quickSort<int>(nums, 0, nums.size() - 1);
		return nums;
	}

“912. Sort an Array” QuickSort Golang

func quick(nums []int) {
    if len(nums) <= 1 {
        return
    }
    pivot, l, r := nums[0], 0, len(nums)-1
    for l < r {
        for l < r && nums[r] >= pivot {
            r--
        }
        nums[l], nums[r] = nums[r], nums[l]
        for l < r && nums[l] <= pivot {
            l++
        }
        nums[l], nums[r] = nums[r], nums[l]
    }
    quick(nums[:l])
    quick(nums[l+1:])
}

“1833. Maximum Ice Cream Bars”

func maxIceCream(costs []int, coins int) (ans int) {
    const MX int = 1e5
    freq := [MX + 1]int{}
    for _, c := range costs {
        freq[c]++
    }
    for i := 1; i <= MX && coins >= i; i++ {
        c := min(freq[i], coins/i)
        ans += c
        coins -= i * c
    }
    return
}

“1846. Maximum Element After Decreasing and Rearranging”

func maximumElementAfterDecrementingAndRearranging(arr []int) (maxVal int) {
    n := len(arr)
    bucket := make([]int, n+1)
    for _, a := range arr {
        bucket[min(a, n)]++
    }
    for i := 1; i <= n; i++ {
        maxVal = min(i, maxVal+bucket[i])
    }
    return maxVal
}