LeetCode 排序


基礎部分

912. 排序數組

中等

給你一個整數數組 nums,請你將該數組升序排列。

示例 1:

輸入:nums = [5,2,3,1]
輸出:[1,2,3,5]

示例 2:

輸入:nums = [5,1,1,2,0,0]
輸出:[0,0,1,1,2,5]

提示:

  1. 1 <= nums.length <= 50000
  2. -50000 <= nums[i] <= 50000
class Solution {
    public int[] sortArray(int[] nums) {
        quickSort(nums,0,nums.length-1);
        return nums;
    }

    private void quickSort(int[] nums, int l, int r) {
        if (l >= r) return;
        int mid = pattern(nums,l,r);
        if (mid != l){
            int tmp = nums[mid];
            nums[mid] = nums[l];
            nums[l] = tmp;
        }
        quickSort(nums,l,mid-1);
        quickSort(nums,mid+1,r);
    }

    private int pattern(int[] nums, int l, int r) {
        int first = nums[l];
        int i = l;
        int j = r + 1;
        while (i < j){
            do { //先判斷后加,會多加一個,所以 do..while
                i++;
            }while (nums[i] < first && i < r);
            do {
                j--;
            }while (nums[j] > first && j > l);
            if (i >= j) break; //弄多了就換回來了,所以檢查一下
            int tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
        }
        return j;
    }
}

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 ≤ 數組的長度。

//減治的快排
class Solution {
    public int findKthLargest(int[] nums, int k){
        quickSort(nums,k-1,0,nums.length-1);
        return nums[k-1];
    }

    private void quickSort(int[] nums, int index, int l, int r) {
        if (l >= r) return;
        int mid = pattern(nums,l,r);
        if (mid != l){
            int tmp = nums[mid];
            nums[mid] = nums[l];
            nums[l] = tmp;
        }
        if (mid > index) quickSort(nums,index,l,mid-1);
        else quickSort(nums,index,mid+1,r);
    }

    private int pattern(int[] nums, int l, int r) {
        int first = nums[l];
        int i = l;
        int j = r + 1;
        while (i < j){
            do {
                i++;
            }while (nums[i] > first && i < r);
            do {
                j--;
            }while (nums[j] < first && j > l);
            if (i >= j) break;
            int tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
        }
        return j;
    }
}
//堆排序:建立k大小的小根堆,堆頂即為所求
class Solution {
    public int findKthLargest(int[] nums, int k){ //O(n*logk)
        //PriorityQueue 優先級隊列,底層是二叉堆
        //(n1,n2)->n1-n2 小根堆
        PriorityQueue<Integer> heap = new PriorityQueue<>((n1,n2)->n1-n2);
        for (int num : nums) {
            heap.add(num); //O(logk)
            if (heap.size() > k) heap.poll(); //O(logk)
        }
        return heap.poll();
    }
}

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 是數組的大小。
  • 題目數據保證答案唯一,換句話說,數組中前 k 個高頻元素的集合是唯一的。
  • 你可以按任意順序返回答案。
// 設置若干個桶,每個桶存儲出現頻率相同的數。桶的下標表示數出現的頻率,即第 i 個桶中存儲的數出現的頻率為 i。
// 把數都放到桶之后,從后向前遍歷桶,最先得到的 k 個數就是出現頻率最多的的 k 個數。
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); //數字頻數哈希表
        List<Integer>[] buckets = new LinkedList[nums.length+1];
        for (Integer num : map.keySet()){
            int freq = map.get(num);
            if (buckets[freq] == null) //沒初始化=>沒有內存=>沒法add
                buckets[freq] = new LinkedList<>();
            buckets[freq].add(num); //放到對應頻數的桶里
        }
        int[] res = new int[k];
        int index = 0;
        for (int i = buckets.length-1; i > 0 && index < k; i--) {
            if (buckets[i] == null) continue;
            for (Integer num : buckets[i])
                res[index++] = num;
        }
        return res;
    }
}

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'被認為是兩種不同的字符。
class Solution {
    public String frequencySort(String s) {
        char[] chars = s.toCharArray();
        Map<Character,Integer> map = new HashMap<>();
        for (char aChar : chars)
            map.put(aChar,map.getOrDefault(aChar,0)+1);
        List<Character>[] buckets = new LinkedList[chars.length+1];
        for (Character c : map.keySet()) {
            int freq = map.get(c);
            if (buckets[freq] == null) buckets[freq] = new LinkedList<>();
            buckets[freq].add(c);
        }
        StringBuilder res = new StringBuilder();
        for (int i = buckets.length - 1; i > 0; i--) {
            if (buckets[i] == null) continue;
            for (Character c : buckets[i]) {
                for (int j = 0; j < i; j++) res.append(c);
                if (res.length() == chars.length) break;
            }
        }
        return res.toString();
    }
}

75. 顏色分類

中等

給定一個包含紅色、白色和藍色,一共 n 個元素的數組,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。

此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。

注意:
不能使用代碼庫中的排序函數來解決這道題。

示例:

輸入: [2,0,2,1,1,0]
輸出: [0,0,1,1,2,2]

進階:

  • 一個直觀的解決方案是使用計數排序的兩趟掃描算法。
    首先,迭代計算出0、1 和 2 元素的個數,然后按照0、1、2的排序,重寫當前數組。
  • 你能想出一個僅使用常數空間的一趟掃描算法嗎?
// 0跟head換,head++;2跟tail換,tail--
// 換就完事了,判斷一樣費時間
// 注意:跟tail換時指針不往前走,因為不知道換個啥回來
class Solution {
    public void sortColors(int[] nums) {
        int head = 0, curr = 0;
        int tail = nums.length - 1;
        int tmp;
        while (curr <= tail) {
            if (nums[curr] == 0) {
                tmp = nums[head];
                nums[head++] = nums[curr];
                nums[curr++] = tmp;
            }
            else if (nums[curr] == 2) {
                tmp = nums[curr];
                nums[curr] = nums[tail];
                nums[tail--] = tmp;
            }
            else curr++;
        }
    }
}

頻率排序

853. 車隊

中等

N 輛車沿着一條車道駛向位於 target 英里之外的共同目的地。

每輛車 i 以恆定的速度 speed[i] (英里/小時),從初始位置 position[i] (英里) 沿車道駛向目的地。

一輛車永遠不會超過前面的另一輛車,但它可以追上去,並與前車以相同的速度緊接着行駛。

此時,我們會忽略這兩輛車之間的距離,也就是說,它們被假定處於相同的位置。

車隊 是一些由行駛在相同位置、具有相同速度的車組成的非空集合。注意,一輛車也可以是一個車隊。

即便一輛車在目的地才趕上了一個車隊,它們仍然會被視作是同一個車隊。

會有多少車隊到達目的地?

示例:

輸入:target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3]
輸出:3
解釋:
從 10 和 8 開始的車會組成一個車隊,它們在 12 處相遇。
從 0 處開始的車無法追上其它車,所以它自己就是一個車隊。
從 5 和 3 開始的車會組成一個車隊,它們在 6 處相遇。
請注意,在到達目的地之前沒有其它車會遇到這些車隊,所以答案是 3。

提示:

  1. 0 <= N <= 10 ^ 4
  2. 0 < target <= 10 ^ 6
  3. 0 < speed[i] <= 10 ^ 6
  4. 0 <= position[i] < target
  5. 所有車的初始位置各不相同。
class Car{ //用類來整合比別的數據結構舒服
    int position;
    double time;

    public Car(int position, double time) {
        this.position = position;
        this.time = time;
    }
}
class Solution {
    public int carFleet(int target, int[] position, int[] speed) {
        int len = position.length;
        Car[] cars = new Car[len];
        for (int i = 0; i < len; i++)
            cars[i] = new Car(position[i],(double)(target-position[i])/speed[i]);
        Arrays.sort(cars,(x,y)->(y.position-x.position)); //按位置的降序
        int res = 0;
        for (int i = 0; i < len; i++) {
            res++;
            double head = cars[i].time;
            while (i < len && cars[i].time <= head) i++; //在我后邊的,用時小於等於我的,才能追上我,和我同步到達
            i--; //for自帶自增,會多加一次,所以減回來
        }
        return res;
    }
}

179. 最大數

中等

給定一組非負整數,重新排列它們的順序使之組成一個最大的整數。

示例 1:

輸入: [10,2]
輸出: 210

示例 2:

輸入: [3,30,34,5,9]
輸出: 9534330

說明: 輸出結果可能非常大,所以你需要返回一個字符串而不是整數。

class Solution {
    public String largestNumber(int[] nums) {
        //這樣寫會報錯,基本數據類型都不能這么些,所以后邊先把int[]轉成了String[]
        //Arrays.sort(nums,(x,y) -> (String.valueOf(y)+String.valueOf(x)).compareTo(String.valueOf(x)+String.valueOf(y));
        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) -> (y + x).compareTo(x + y));
        StringBuilder res = new StringBuilder();
        for(String s : strs)
            res.append(s);
        return res.toString();
    }
}

148. 排序鏈表

中等

O(n log n) 時間復雜度和常數級空間復雜度下,對鏈表進行排序。

示例 1:

輸入: 4->2->1->3
輸出: 1->2->3->4

示例 2:

輸入: -1->5->3->4->0
輸出: -1->0->3->4->5
class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) 
            return head; //遞歸到頭只有head了,這時候開始merge
        ListNode slow = head, fast = head.next;
        while (fast != null && fast.next != null){ //二分鏈表
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode head2 = slow.next;
        slow.next = null;
        return merge(sortList(head),sortList(head2)); //遞歸合並
    }

    private ListNode merge(ListNode a,ListNode b) { //合並有序鏈表
        ListNode node = new ListNode(0);
        ListNode p = node;
        while (a != null && b != null){
            if (a.val < b.val){
                p.next = a;
                a = a.next;
            }else {
                p.next = b;
                b = b.next;
            }
            p = p.next;
        }
        p.next = a != null ? a : b;
        return node.next;
    }
}

56. 合並區間

中等

給出一個區間的集合,請合並所有重疊的區間。

示例 1:

輸入: [[1,3],[2,6],[8,10],[15,18]]
輸出: [[1,6],[8,10],[15,18]]
解釋: 區間 [1,3] 和 [2,6] 重疊, 將它們合並為 [1,6].

示例 2:

輸入: [[1,4],[4,5]]
輸出: [[1,5]]
解釋: 區間 [1,4] 和 [4,5] 可被視為重疊區間。
class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length < 2) return intervals;
        Arrays.sort(intervals,(a,b)->(a[0]-b[0]));
        List<int[]> list = new LinkedList<>();
        list.add(intervals[0]);
        for (int i = 1; i < intervals.length; i++) {
            int tail = list.get(list.size()-1)[1];
            if (intervals[i][0] > tail){
                list.add(intervals[i]);
            }else if (intervals[i][1] > tail){
                list.get(list.size()-1)[1] = intervals[i][1];
            }
        }
        int len = list.size();
        int[][] res = new int[len][2];
        for (int i = 0; i < len; i++) {
            res[i] = list.get(i);
        }
        return res;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM