Skip to content

Latest commit

 

History

History
280 lines (237 loc) · 7.91 KB

排序.md

File metadata and controls

280 lines (237 loc) · 7.91 KB

剑指 Offer 45. 把数组排成最小的数

剑指 Offer 45. 把数组排成最小的数

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

示例 1:

输入: [10,2]
输出: "102"
示例 2:

输入: [3,30,34,5,9]
输出: "3033459"
 

提示:

0 < nums.length <= 100
说明:

输出结果可能非常大,所以你需要返回一个字符串而不是整数
拼接起来的数字可能会有前导 0,最后结果不需要去掉前导 0

快速排序

class Solution {
    public String minNumber(int[] nums) {
        int n = nums.length;
        String[] strs = new String[n];
        int index = 0;
        for (int num : nums) {
            strs[index++] = String.valueOf(num);
        }
        fastSort(strs, 0, n - 1);
        StringBuilder sb = new StringBuilder();
        for (String str : strs) {
            sb.append(str);
        }
        return sb.toString();
    }
    private void fastSort(String[] strs, int low, int high) {
        if (low >= high) {
            return;
        }
        int i = low, j = high;
        String tmp = strs[i];
        while (i < j) {
            while ((strs[j] + strs[low]).compareTo(strs[low] + strs[j]) >= 0 && i < j) {
                j--;
            }
            while ((strs[i] + strs[low]).compareTo(strs[low] + strs[i]) <= 0 && i < j) {
                i++;
            }
            tmp = strs[i];
            strs[i] = strs[j];
            strs[j] = tmp;
        }
        strs[i] = strs[low];
        strs[low] = tmp;
        fastSort(strs, low, j - 1);
        fastSort(strs, j + 1, high);
    }
}

Arrays.sort

class Solution {
    public String minNumber(int[] nums) {
        String[] strs = new String[nums.length];
        for (int i = 0; i < nums.length; i++) {
            strs[i] = String.valueOf(nums[i]);
        }
        Arrays.sort(strs, (x, y) -> (x + y).compareTo(y + x));
        StringBuilder res = new StringBuilder();
        for(String s : strs) {
            res.append(s);
        }
        return res.toString();
    }
}

215. 数组中的第K个最大元素

215. 数组中的第K个最大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4 说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

用堆处理

维持一个包含k个元素的小顶堆,遍历一遍nums,取出堆顶即可。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        Queue<Integer> minQueue = new PriorityQueue<>();
        for (int num : nums) {
            minQueue.offer(num);
            if (minQueue.size() > k) {
                minQueue.poll();
            }
        }
        return minQueue.peek();
    }
}

快速选择

利用(从小到大)快排的partition操作把数组两边划分成左边小于等于v, 右边大于等于v。(v为基准值),位置记为p。 若右边的元素比不少于k个,说明第k大的元素在数组的右边, 否则第k大的元素在数组的左边。 注意: 若右边的元素比少于k个,设右边元素个数为lenR,因为右边边已经有lenR个数比现有的位置大了,所以在在数组左边找 第k - lenR大的数。

该递归函数不消耗空间,因为并不需要保存变量。每次平均把数组砍一半,要不递归左边,或者递归右边。

class Solution {
public:
    int partition(vector<int>& nums, int l, int r)
    {
        int x = nums[l+r >> 1];
        int i = l - 1, j = r + 1;
        while(i < j)
        {
            do ++i; while(nums[i] < x);
            do --j; while(nums[j] > x);
            if(i < j)
                swap(nums[i], nums[j]);
        }
        return j;
    }
    int find_num(vector<int>& nums, int l, int r, int k)
    {
        if(l >= r) return nums[r];
        int p = partition(nums, l, r);
        return (r - p) >= k ? find_num(nums, p + 1, r, k) : find_num(nums, 0, p, k-(r - p));
    }
    int findKthLargest(vector<int>& nums, int k) {
        return find_num(nums, 0, nums.size() - 1, k);
    }
};

平均 时间:O(n) & 空间:O(1) || 最坏:时间:O(n^2) 空间 O(1)

347. 前 K 个高频元素

347. 前 K 个高频元素

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2:

输入: nums = [1], k = 1 输出: [1] 说明:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

HashMap+PriorityQueue

统计nums中每个元素的次数,,存入hashmap,然后维护一个的大顶堆

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        int[] res = new int[k];
        Queue<Pair<Integer, Integer>> maxHeap = new PriorityQueue<Pair<Integer, Integer>>((Pair<Integer, Integer> p1, Pair<Integer, Integer> p2) -> {
            if (p1.getValue() < p2.getValue()) {
                return 1;
            } else if (p1.getValue().equals(p2.getValue())){
                return 0;
            } else {
                return -1;
            }
        });
        for (Integer value : map.keySet()) {
            maxHeap.offer(new Pair<>(value, map.get(value)));
        }
        for (int i = 0; i < k; i++) {
            res[i] = maxHeap.poll().getKey();
        }
        return res;
    }
}

451. 根据字符出现频率排序

451. 根据字符出现频率排序

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:

输入: "tree"

输出: "eert"

解释: 'e'出现两次,'r'和't'都只出现一次。 因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2:

输入: "cccaaa"

输出: "cccaaa"

解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。 注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3:

输入: "Aabb"

输出: "bbAa"

解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。 注意'A'和'a'被认为是两种不同的字符。

HashMap+PriorityQueue

记录每个字符出现的次数, 然后维护一个大顶堆,每次取出堆顶出去就好了。

class Solution {
    public String frequencySort(String s) {
        int n = s.length();
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        Queue<Pair<Character, Integer>> maxHeap = new PriorityQueue<Pair<Character, Integer>>((x, y) -> {
            if (x.getValue() < y.getValue()) {
                return 1;
            } else if (x.getValue().equals(y.getValue())) {
                return 0;
            } else {
                return -1;
            }
        });
        for (Character value : map.keySet()) {
            maxHeap.offer(new Pair<Character, Integer>(value, map.get(value)));
        }
        StringBuilder sb = new StringBuilder();
        while (!maxHeap.isEmpty()) {
            Pair<Character, Integer> pair = maxHeap.poll();
            int value = pair.getValue();
            while (value-- > 0) {
                sb.append(pair.getKey());
            }
        }
        return sb.toString();
    }
}